• Main Page
  • Classes
  • Files
  • File List

CKeyState.cpp

00001 /*
00002  * synergy -- mouse and keyboard sharing utility
00003  * Copyright (C) 2012 Bolton Software Ltd.
00004  * Copyright (C) 2004 Chris Schoeneman
00005  * 
00006  * This package is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * found in the file COPYING that should have accompanied this file.
00009  * 
00010  * This package is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 #include "CKeyState.h"
00020 #include "CLog.h"
00021 #include <cstring>
00022 #include <algorithm>
00023 #include <iterator>
00024 #include <list>
00025 
00026 static const KeyButton kButtonMask = (KeyButton)(IKeyState::kNumButtons - 1);
00027 
00028 static const KeyID s_decomposeTable[] = {
00029     // spacing version of dead keys
00030     0x0060, 0x0300, 0x0020, 0, // grave,        dead_grave,       space
00031     0x00b4, 0x0301, 0x0020, 0, // acute,        dead_acute,       space
00032     0x005e, 0x0302, 0x0020, 0, // asciicircum,  dead_circumflex,  space
00033     0x007e, 0x0303, 0x0020, 0, // asciitilde,   dead_tilde,       space
00034     0x00a8, 0x0308, 0x0020, 0, // diaeresis,    dead_diaeresis,   space
00035     0x00b0, 0x030a, 0x0020, 0, // degree,       dead_abovering,   space
00036     0x00b8, 0x0327, 0x0020, 0, // cedilla,      dead_cedilla,     space
00037     0x02db, 0x0328, 0x0020, 0, // ogonek,       dead_ogonek,      space
00038     0x02c7, 0x030c, 0x0020, 0, // caron,        dead_caron,       space
00039     0x02d9, 0x0307, 0x0020, 0, // abovedot,     dead_abovedot,    space
00040     0x02dd, 0x030b, 0x0020, 0, // doubleacute,  dead_doubleacute, space
00041     0x02d8, 0x0306, 0x0020, 0, // breve,        dead_breve,       space
00042     0x00af, 0x0304, 0x0020, 0, // macron,       dead_macron,      space
00043 
00044     // Latin-1 (ISO 8859-1)
00045     0x00c0, 0x0300, 0x0041, 0, // Agrave,       dead_grave,       A
00046     0x00c1, 0x0301, 0x0041, 0, // Aacute,       dead_acute,       A
00047     0x00c2, 0x0302, 0x0041, 0, // Acircumflex,  dead_circumflex,  A
00048     0x00c3, 0x0303, 0x0041, 0, // Atilde,       dead_tilde,       A
00049     0x00c4, 0x0308, 0x0041, 0, // Adiaeresis,   dead_diaeresis,   A
00050     0x00c5, 0x030a, 0x0041, 0, // Aring,        dead_abovering,   A
00051     0x00c7, 0x0327, 0x0043, 0, // Ccedilla,     dead_cedilla,     C
00052     0x00c8, 0x0300, 0x0045, 0, // Egrave,       dead_grave,       E
00053     0x00c9, 0x0301, 0x0045, 0, // Eacute,       dead_acute,       E
00054     0x00ca, 0x0302, 0x0045, 0, // Ecircumflex,  dead_circumflex,  E
00055     0x00cb, 0x0308, 0x0045, 0, // Ediaeresis,   dead_diaeresis,   E
00056     0x00cc, 0x0300, 0x0049, 0, // Igrave,       dead_grave,       I
00057     0x00cd, 0x0301, 0x0049, 0, // Iacute,       dead_acute,       I
00058     0x00ce, 0x0302, 0x0049, 0, // Icircumflex,  dead_circumflex,  I
00059     0x00cf, 0x0308, 0x0049, 0, // Idiaeresis,   dead_diaeresis,   I
00060     0x00d1, 0x0303, 0x004e, 0, // Ntilde,       dead_tilde,       N
00061     0x00d2, 0x0300, 0x004f, 0, // Ograve,       dead_grave,       O
00062     0x00d3, 0x0301, 0x004f, 0, // Oacute,       dead_acute,       O
00063     0x00d4, 0x0302, 0x004f, 0, // Ocircumflex,  dead_circumflex,  O
00064     0x00d5, 0x0303, 0x004f, 0, // Otilde,       dead_tilde,       O
00065     0x00d6, 0x0308, 0x004f, 0, // Odiaeresis,   dead_diaeresis,   O
00066     0x00d9, 0x0300, 0x0055, 0, // Ugrave,       dead_grave,       U
00067     0x00da, 0x0301, 0x0055, 0, // Uacute,       dead_acute,       U
00068     0x00db, 0x0302, 0x0055, 0, // Ucircumflex,  dead_circumflex,  U
00069     0x00dc, 0x0308, 0x0055, 0, // Udiaeresis,   dead_diaeresis,   U
00070     0x00dd, 0x0301, 0x0059, 0, // Yacute,       dead_acute,       Y
00071     0x00e0, 0x0300, 0x0061, 0, // agrave,       dead_grave,       a
00072     0x00e1, 0x0301, 0x0061, 0, // aacute,       dead_acute,       a
00073     0x00e2, 0x0302, 0x0061, 0, // acircumflex,  dead_circumflex,  a
00074     0x00e3, 0x0303, 0x0061, 0, // atilde,       dead_tilde,       a
00075     0x00e4, 0x0308, 0x0061, 0, // adiaeresis,   dead_diaeresis,   a
00076     0x00e5, 0x030a, 0x0061, 0, // aring,        dead_abovering,   a
00077     0x00e7, 0x0327, 0x0063, 0, // ccedilla,     dead_cedilla,     c
00078     0x00e8, 0x0300, 0x0065, 0, // egrave,       dead_grave,       e
00079     0x00e9, 0x0301, 0x0065, 0, // eacute,       dead_acute,       e
00080     0x00ea, 0x0302, 0x0065, 0, // ecircumflex,  dead_circumflex,  e
00081     0x00eb, 0x0308, 0x0065, 0, // ediaeresis,   dead_diaeresis,   e
00082     0x00ec, 0x0300, 0x0069, 0, // igrave,       dead_grave,       i
00083     0x00ed, 0x0301, 0x0069, 0, // iacute,       dead_acute,       i
00084     0x00ee, 0x0302, 0x0069, 0, // icircumflex,  dead_circumflex,  i
00085     0x00ef, 0x0308, 0x0069, 0, // idiaeresis,   dead_diaeresis,   i
00086     0x00f1, 0x0303, 0x006e, 0, // ntilde,       dead_tilde,       n
00087     0x00f2, 0x0300, 0x006f, 0, // ograve,       dead_grave,       o
00088     0x00f3, 0x0301, 0x006f, 0, // oacute,       dead_acute,       o
00089     0x00f4, 0x0302, 0x006f, 0, // ocircumflex,  dead_circumflex,  o
00090     0x00f5, 0x0303, 0x006f, 0, // otilde,       dead_tilde,       o
00091     0x00f6, 0x0308, 0x006f, 0, // odiaeresis,   dead_diaeresis,   o
00092     0x00f9, 0x0300, 0x0075, 0, // ugrave,       dead_grave,       u
00093     0x00fa, 0x0301, 0x0075, 0, // uacute,       dead_acute,       u
00094     0x00fb, 0x0302, 0x0075, 0, // ucircumflex,  dead_circumflex,  u
00095     0x00fc, 0x0308, 0x0075, 0, // udiaeresis,   dead_diaeresis,   u
00096     0x00fd, 0x0301, 0x0079, 0, // yacute,       dead_acute,       y
00097     0x00ff, 0x0308, 0x0079, 0, // ydiaeresis,   dead_diaeresis,   y
00098 
00099     // Latin-2 (ISO 8859-2)
00100     0x0104, 0x0328, 0x0041, 0, // Aogonek,      dead_ogonek,      A
00101     0x013d, 0x030c, 0x004c, 0, // Lcaron,       dead_caron,       L
00102     0x015a, 0x0301, 0x0053, 0, // Sacute,       dead_acute,       S
00103     0x0160, 0x030c, 0x0053, 0, // Scaron,       dead_caron,       S
00104     0x015e, 0x0327, 0x0053, 0, // Scedilla,     dead_cedilla,     S
00105     0x0164, 0x030c, 0x0054, 0, // Tcaron,       dead_caron,       T
00106     0x0179, 0x0301, 0x005a, 0, // Zacute,       dead_acute,       Z
00107     0x017d, 0x030c, 0x005a, 0, // Zcaron,       dead_caron,       Z
00108     0x017b, 0x0307, 0x005a, 0, // Zabovedot,    dead_abovedot,    Z
00109     0x0105, 0x0328, 0x0061, 0, // aogonek,      dead_ogonek,      a
00110     0x013e, 0x030c, 0x006c, 0, // lcaron,       dead_caron,       l
00111     0x015b, 0x0301, 0x0073, 0, // sacute,       dead_acute,       s
00112     0x0161, 0x030c, 0x0073, 0, // scaron,       dead_caron,       s
00113     0x015f, 0x0327, 0x0073, 0, // scedilla,     dead_cedilla,     s
00114     0x0165, 0x030c, 0x0074, 0, // tcaron,       dead_caron,       t
00115     0x017a, 0x0301, 0x007a, 0, // zacute,       dead_acute,       z
00116     0x017e, 0x030c, 0x007a, 0, // zcaron,       dead_caron,       z
00117     0x017c, 0x0307, 0x007a, 0, // zabovedot,    dead_abovedot,    z
00118     0x0154, 0x0301, 0x0052, 0, // Racute,       dead_acute,       R
00119     0x0102, 0x0306, 0x0041, 0, // Abreve,       dead_breve,       A
00120     0x0139, 0x0301, 0x004c, 0, // Lacute,       dead_acute,       L
00121     0x0106, 0x0301, 0x0043, 0, // Cacute,       dead_acute,       C
00122     0x010c, 0x030c, 0x0043, 0, // Ccaron,       dead_caron,       C
00123     0x0118, 0x0328, 0x0045, 0, // Eogonek,      dead_ogonek,      E
00124     0x011a, 0x030c, 0x0045, 0, // Ecaron,       dead_caron,       E
00125     0x010e, 0x030c, 0x0044, 0, // Dcaron,       dead_caron,       D
00126     0x0143, 0x0301, 0x004e, 0, // Nacute,       dead_acute,       N
00127     0x0147, 0x030c, 0x004e, 0, // Ncaron,       dead_caron,       N
00128     0x0150, 0x030b, 0x004f, 0, // Odoubleacute, dead_doubleacute, O
00129     0x0158, 0x030c, 0x0052, 0, // Rcaron,       dead_caron,       R
00130     0x016e, 0x030a, 0x0055, 0, // Uring,        dead_abovering,   U
00131     0x0170, 0x030b, 0x0055, 0, // Udoubleacute, dead_doubleacute, U
00132     0x0162, 0x0327, 0x0054, 0, // Tcedilla,     dead_cedilla,     T
00133     0x0155, 0x0301, 0x0072, 0, // racute,       dead_acute,       r
00134     0x0103, 0x0306, 0x0061, 0, // abreve,       dead_breve,       a
00135     0x013a, 0x0301, 0x006c, 0, // lacute,       dead_acute,       l
00136     0x0107, 0x0301, 0x0063, 0, // cacute,       dead_acute,       c
00137     0x010d, 0x030c, 0x0063, 0, // ccaron,       dead_caron,       c
00138     0x0119, 0x0328, 0x0065, 0, // eogonek,      dead_ogonek,      e
00139     0x011b, 0x030c, 0x0065, 0, // ecaron,       dead_caron,       e
00140     0x010f, 0x030c, 0x0064, 0, // dcaron,       dead_caron,       d
00141     0x0144, 0x0301, 0x006e, 0, // nacute,       dead_acute,       n
00142     0x0148, 0x030c, 0x006e, 0, // ncaron,       dead_caron,       n
00143     0x0151, 0x030b, 0x006f, 0, // odoubleacute, dead_doubleacute, o
00144     0x0159, 0x030c, 0x0072, 0, // rcaron,       dead_caron,       r
00145     0x016f, 0x030a, 0x0075, 0, // uring,        dead_abovering,   u
00146     0x0171, 0x030b, 0x0075, 0, // udoubleacute, dead_doubleacute, u
00147     0x0163, 0x0327, 0x0074, 0, // tcedilla,     dead_cedilla,     t
00148 
00149     // Latin-3 (ISO 8859-3)
00150     0x0124, 0x0302, 0x0048, 0, // Hcircumflex,  dead_circumflex,  H
00151     0x0130, 0x0307, 0x0049, 0, // Iabovedot,    dead_abovedot,    I
00152     0x011e, 0x0306, 0x0047, 0, // Gbreve,       dead_breve,       G
00153     0x0134, 0x0302, 0x004a, 0, // Jcircumflex,  dead_circumflex,  J
00154     0x0125, 0x0302, 0x0068, 0, // hcircumflex,  dead_circumflex,  h
00155     0x011f, 0x0306, 0x0067, 0, // gbreve,       dead_breve,       g
00156     0x0135, 0x0302, 0x006a, 0, // jcircumflex,  dead_circumflex,  j
00157     0x010a, 0x0307, 0x0043, 0, // Cabovedot,    dead_abovedot,    C
00158     0x0108, 0x0302, 0x0043, 0, // Ccircumflex,  dead_circumflex,  C
00159     0x0120, 0x0307, 0x0047, 0, // Gabovedot,    dead_abovedot,    G
00160     0x011c, 0x0302, 0x0047, 0, // Gcircumflex,  dead_circumflex,  G
00161     0x016c, 0x0306, 0x0055, 0, // Ubreve,       dead_breve,       U
00162     0x015c, 0x0302, 0x0053, 0, // Scircumflex,  dead_circumflex,  S
00163     0x010b, 0x0307, 0x0063, 0, // cabovedot,    dead_abovedot,    c
00164     0x0109, 0x0302, 0x0063, 0, // ccircumflex,  dead_circumflex,  c
00165     0x0121, 0x0307, 0x0067, 0, // gabovedot,    dead_abovedot,    g
00166     0x011d, 0x0302, 0x0067, 0, // gcircumflex,  dead_circumflex,  g
00167     0x016d, 0x0306, 0x0075, 0, // ubreve,       dead_breve,       u
00168     0x015d, 0x0302, 0x0073, 0, // scircumflex,  dead_circumflex,  s
00169 
00170     // Latin-4 (ISO 8859-4)
00171     0x0156, 0x0327, 0x0052, 0, // Rcedilla,     dead_cedilla,     R
00172     0x0128, 0x0303, 0x0049, 0, // Itilde,       dead_tilde,       I
00173     0x013b, 0x0327, 0x004c, 0, // Lcedilla,     dead_cedilla,     L
00174     0x0112, 0x0304, 0x0045, 0, // Emacron,      dead_macron,      E
00175     0x0122, 0x0327, 0x0047, 0, // Gcedilla,     dead_cedilla,     G
00176     0x0157, 0x0327, 0x0072, 0, // rcedilla,     dead_cedilla,     r
00177     0x0129, 0x0303, 0x0069, 0, // itilde,       dead_tilde,       i
00178     0x013c, 0x0327, 0x006c, 0, // lcedilla,     dead_cedilla,     l
00179     0x0113, 0x0304, 0x0065, 0, // emacron,      dead_macron,      e
00180     0x0123, 0x0327, 0x0067, 0, // gcedilla,     dead_cedilla,     g
00181     0x0100, 0x0304, 0x0041, 0, // Amacron,      dead_macron,      A
00182     0x012e, 0x0328, 0x0049, 0, // Iogonek,      dead_ogonek,      I
00183     0x0116, 0x0307, 0x0045, 0, // Eabovedot,    dead_abovedot,    E
00184     0x012a, 0x0304, 0x0049, 0, // Imacron,      dead_macron,      I
00185     0x0145, 0x0327, 0x004e, 0, // Ncedilla,     dead_cedilla,     N
00186     0x014c, 0x0304, 0x004f, 0, // Omacron,      dead_macron,      O
00187     0x0136, 0x0327, 0x004b, 0, // Kcedilla,     dead_cedilla,     K
00188     0x0172, 0x0328, 0x0055, 0, // Uogonek,      dead_ogonek,      U
00189     0x0168, 0x0303, 0x0055, 0, // Utilde,       dead_tilde,       U
00190     0x016a, 0x0304, 0x0055, 0, // Umacron,      dead_macron,      U
00191     0x0101, 0x0304, 0x0061, 0, // amacron,      dead_macron,      a
00192     0x012f, 0x0328, 0x0069, 0, // iogonek,      dead_ogonek,      i
00193     0x0117, 0x0307, 0x0065, 0, // eabovedot,    dead_abovedot,    e
00194     0x012b, 0x0304, 0x0069, 0, // imacron,      dead_macron,      i
00195     0x0146, 0x0327, 0x006e, 0, // ncedilla,     dead_cedilla,     n
00196     0x014d, 0x0304, 0x006f, 0, // omacron,      dead_macron,      o
00197     0x0137, 0x0327, 0x006b, 0, // kcedilla,     dead_cedilla,     k
00198     0x0173, 0x0328, 0x0075, 0, // uogonek,      dead_ogonek,      u
00199     0x0169, 0x0303, 0x0075, 0, // utilde,       dead_tilde,       u
00200     0x016b, 0x0304, 0x0075, 0, // umacron,      dead_macron,      u
00201 
00202     // Latin-8 (ISO 8859-14)
00203     0x1e02, 0x0307, 0x0042, 0, // Babovedot,    dead_abovedot,    B
00204     0x1e03, 0x0307, 0x0062, 0, // babovedot,    dead_abovedot,    b
00205     0x1e0a, 0x0307, 0x0044, 0, // Dabovedot,    dead_abovedot,    D
00206     0x1e80, 0x0300, 0x0057, 0, // Wgrave,       dead_grave,       W
00207     0x1e82, 0x0301, 0x0057, 0, // Wacute,       dead_acute,       W
00208     0x1e0b, 0x0307, 0x0064, 0, // dabovedot,    dead_abovedot,    d
00209     0x1ef2, 0x0300, 0x0059, 0, // Ygrave,       dead_grave,       Y
00210     0x1e1e, 0x0307, 0x0046, 0, // Fabovedot,    dead_abovedot,    F
00211     0x1e1f, 0x0307, 0x0066, 0, // fabovedot,    dead_abovedot,    f
00212     0x1e40, 0x0307, 0x004d, 0, // Mabovedot,    dead_abovedot,    M
00213     0x1e41, 0x0307, 0x006d, 0, // mabovedot,    dead_abovedot,    m
00214     0x1e56, 0x0307, 0x0050, 0, // Pabovedot,    dead_abovedot,    P
00215     0x1e81, 0x0300, 0x0077, 0, // wgrave,       dead_grave,       w
00216     0x1e57, 0x0307, 0x0070, 0, // pabovedot,    dead_abovedot,    p
00217     0x1e83, 0x0301, 0x0077, 0, // wacute,       dead_acute,       w
00218     0x1e60, 0x0307, 0x0053, 0, // Sabovedot,    dead_abovedot,    S
00219     0x1ef3, 0x0300, 0x0079, 0, // ygrave,       dead_grave,       y
00220     0x1e84, 0x0308, 0x0057, 0, // Wdiaeresis,   dead_diaeresis,   W
00221     0x1e85, 0x0308, 0x0077, 0, // wdiaeresis,   dead_diaeresis,   w
00222     0x1e61, 0x0307, 0x0073, 0, // sabovedot,    dead_abovedot,    s
00223     0x0174, 0x0302, 0x0057, 0, // Wcircumflex,  dead_circumflex,  W
00224     0x1e6a, 0x0307, 0x0054, 0, // Tabovedot,    dead_abovedot,    T
00225     0x0176, 0x0302, 0x0059, 0, // Ycircumflex,  dead_circumflex,  Y
00226     0x0175, 0x0302, 0x0077, 0, // wcircumflex,  dead_circumflex,  w
00227     0x1e6b, 0x0307, 0x0074, 0, // tabovedot,    dead_abovedot,    t
00228     0x0177, 0x0302, 0x0079, 0, // ycircumflex,  dead_circumflex,  y
00229 
00230     // Latin-9 (ISO 8859-15)
00231     0x0178, 0x0308, 0x0059, 0, // Ydiaeresis,   dead_diaeresis,   Y
00232 
00233     // Compose key sequences
00234     0x00c6, kKeyCompose, 0x0041, 0x0045, 0, // AE,             A,          E
00235     0x00c1, kKeyCompose, 0x0041, 0x0027, 0, // Aacute,         A,          apostrophe
00236     0x00c2, kKeyCompose, 0x0041, 0x0053, 0, // Acircumflex,    A,          asciicircum
00237     0x00c3, kKeyCompose, 0x0041, 0x0022, 0, // Adiaeresis,     A,          quotedbl
00238     0x00c0, kKeyCompose, 0x0041, 0x0060, 0, // Agrave,         A,          grave
00239     0x00c5, kKeyCompose, 0x0041, 0x002a, 0, // Aring,          A,          asterisk
00240     0x00c3, kKeyCompose, 0x0041, 0x007e, 0, // Atilde,         A,          asciitilde
00241     0x00c7, kKeyCompose, 0x0043, 0x002c, 0, // Ccedilla,       C,          comma
00242     0x00d0, kKeyCompose, 0x0044, 0x002d, 0, // ETH,            D,          minus
00243     0x00c9, kKeyCompose, 0x0045, 0x0027, 0, // Eacute,         E,          apostrophe
00244     0x00ca, kKeyCompose, 0x0045, 0x0053, 0, // Ecircumflex,    E,          asciicircum
00245     0x00cb, kKeyCompose, 0x0045, 0x0022, 0, // Ediaeresis,     E,          quotedbl
00246     0x00c8, kKeyCompose, 0x0045, 0x0060, 0, // Egrave,         E,          grave
00247     0x00cd, kKeyCompose, 0x0049, 0x0027, 0, // Iacute,         I,          apostrophe
00248     0x00ce, kKeyCompose, 0x0049, 0x0053, 0, // Icircumflex,    I,          asciicircum
00249     0x00cf, kKeyCompose, 0x0049, 0x0022, 0, // Idiaeresis,     I,          quotedbl
00250     0x00cc, kKeyCompose, 0x0049, 0x0060, 0, // Igrave,         I,          grave
00251     0x00d1, kKeyCompose, 0x004e, 0x007e, 0, // Ntilde,         N,          asciitilde
00252     0x00d3, kKeyCompose, 0x004f, 0x0027, 0, // Oacute,         O,          apostrophe
00253     0x00d4, kKeyCompose, 0x004f, 0x0053, 0, // Ocircumflex,    O,          asciicircum
00254     0x00d6, kKeyCompose, 0x004f, 0x0022, 0, // Odiaeresis,     O,          quotedbl
00255     0x00d2, kKeyCompose, 0x004f, 0x0060, 0, // Ograve,         O,          grave
00256     0x00d8, kKeyCompose, 0x004f, 0x002f, 0, // Ooblique,       O,          slash
00257     0x00d5, kKeyCompose, 0x004f, 0x007e, 0, // Otilde,         O,          asciitilde
00258     0x00de, kKeyCompose, 0x0054, 0x0048, 0, // THORN,          T,          H
00259     0x00da, kKeyCompose, 0x0055, 0x0027, 0, // Uacute,         U,          apostrophe
00260     0x00db, kKeyCompose, 0x0055, 0x0053, 0, // Ucircumflex,    U,          asciicircum
00261     0x00dc, kKeyCompose, 0x0055, 0x0022, 0, // Udiaeresis,     U,          quotedbl
00262     0x00d9, kKeyCompose, 0x0055, 0x0060, 0, // Ugrave,         U,          grave
00263     0x00dd, kKeyCompose, 0x0059, 0x0027, 0, // Yacute,         Y,          apostrophe
00264     0x00e1, kKeyCompose, 0x0061, 0x0027, 0, // aacute,         a,          apostrophe
00265     0x00e2, kKeyCompose, 0x0061, 0x0053, 0, // acircumflex,    a,          asciicircum
00266     0x00b4, kKeyCompose, 0x0027, 0x0027, 0, // acute,          apostrophe, apostrophe
00267     0x00e4, kKeyCompose, 0x0061, 0x0022, 0, // adiaeresis,     a,          quotedbl
00268     0x00e6, kKeyCompose, 0x0061, 0x0065, 0, // ae,             a,          e
00269     0x00e0, kKeyCompose, 0x0061, 0x0060, 0, // agrave,         a,          grave
00270     0x00e5, kKeyCompose, 0x0061, 0x002a, 0, // aring,          a,          asterisk
00271     0x0040, kKeyCompose, 0x0041, 0x0054, 0, // at,             A,          T
00272     0x00e3, kKeyCompose, 0x0061, 0x007e, 0, // atilde,         a,          asciitilde
00273     0x005c, kKeyCompose, 0x002f, 0x002f, 0, // backslash,      slash,      slash
00274     0x007c, kKeyCompose, 0x004c, 0x0056, 0, // bar,            L,          V
00275     0x007b, kKeyCompose, 0x0028, 0x002d, 0, // braceleft,      parenleft,  minus
00276     0x007d, kKeyCompose, 0x0029, 0x002d, 0, // braceright,     parenright, minus
00277     0x005b, kKeyCompose, 0x0028, 0x0028, 0, // bracketleft,    parenleft,  parenleft
00278     0x005d, kKeyCompose, 0x0029, 0x0029, 0, // bracketright,   parenright, parenright
00279     0x00a6, kKeyCompose, 0x0042, 0x0056, 0, // brokenbar,      B,          V
00280     0x00e7, kKeyCompose, 0x0063, 0x002c, 0, // ccedilla,       c,          comma
00281     0x00b8, kKeyCompose, 0x002c, 0x002c, 0, // cedilla,        comma,      comma
00282     0x00a2, kKeyCompose, 0x0063, 0x002f, 0, // cent,           c,          slash
00283     0x00a9, kKeyCompose, 0x0028, 0x0063, 0, // copyright,      parenleft,  c
00284     0x00a4, kKeyCompose, 0x006f, 0x0078, 0, // currency,       o,          x
00285     0x00b0, kKeyCompose, 0x0030, 0x0053, 0, // degree,         0,          asciicircum
00286     0x00a8, kKeyCompose, 0x0022, 0x0022, 0, // diaeresis,      quotedbl,   quotedbl
00287     0x00f7, kKeyCompose, 0x003a, 0x002d, 0, // division,       colon,      minus
00288     0x00e9, kKeyCompose, 0x0065, 0x0027, 0, // eacute,         e,          apostrophe
00289     0x00ea, kKeyCompose, 0x0065, 0x0053, 0, // ecircumflex,    e,          asciicircum
00290     0x00eb, kKeyCompose, 0x0065, 0x0022, 0, // ediaeresis,     e,          quotedbl
00291     0x00e8, kKeyCompose, 0x0065, 0x0060, 0, // egrave,         e,          grave
00292     0x00f0, kKeyCompose, 0x0064, 0x002d, 0, // eth,            d,          minus
00293     0x00a1, kKeyCompose, 0x0021, 0x0021, 0, // exclamdown,     exclam,     exclam
00294     0x00ab, kKeyCompose, 0x003c, 0x003c, 0, // guillemotleft,  less,       less
00295     0x00bb, kKeyCompose, 0x003e, 0x003e, 0, // guillemotright, greater,    greater
00296     0x0023, kKeyCompose, 0x002b, 0x002b, 0, // numbersign,     plus,       plus
00297     0x00ad, kKeyCompose, 0x002d, 0x002d, 0, // hyphen,         minus,      minus
00298     0x00ed, kKeyCompose, 0x0069, 0x0027, 0, // iacute,         i,          apostrophe
00299     0x00ee, kKeyCompose, 0x0069, 0x0053, 0, // icircumflex,    i,          asciicircum
00300     0x00ef, kKeyCompose, 0x0069, 0x0022, 0, // idiaeresis,     i,          quotedbl
00301     0x00ec, kKeyCompose, 0x0069, 0x0060, 0, // igrave,         i,          grave
00302     0x00af, kKeyCompose, 0x002d, 0x0053, 0, // macron,         minus,      asciicircum
00303     0x00ba, kKeyCompose, 0x006f, 0x005f, 0, // masculine,      o,          underscore
00304     0x00b5, kKeyCompose, 0x0075, 0x002f, 0, // mu,             u,          slash
00305     0x00d7, kKeyCompose, 0x0078, 0x0078, 0, // multiply,       x,          x
00306     0x00a0, kKeyCompose, 0x0020, 0x0020, 0, // nobreakspace,   space,      space
00307     0x00ac, kKeyCompose, 0x002c, 0x002d, 0, // notsign,        comma,      minus
00308     0x00f1, kKeyCompose, 0x006e, 0x007e, 0, // ntilde,         n,          asciitilde
00309     0x00f3, kKeyCompose, 0x006f, 0x0027, 0, // oacute,         o,          apostrophe
00310     0x00f4, kKeyCompose, 0x006f, 0x0053, 0, // ocircumflex,    o,          asciicircum
00311     0x00f6, kKeyCompose, 0x006f, 0x0022, 0, // odiaeresis,     o,          quotedbl
00312     0x00f2, kKeyCompose, 0x006f, 0x0060, 0, // ograve,         o,          grave
00313     0x00bd, kKeyCompose, 0x0031, 0x0032, 0, // onehalf,        1,          2
00314     0x00bc, kKeyCompose, 0x0031, 0x0034, 0, // onequarter,     1,          4
00315     0x00b9, kKeyCompose, 0x0031, 0x0053, 0, // onesuperior,    1,          asciicircum
00316     0x00aa, kKeyCompose, 0x0061, 0x005f, 0, // ordfeminine,    a,          underscore
00317     0x00f8, kKeyCompose, 0x006f, 0x002f, 0, // oslash,         o,          slash
00318     0x00f5, kKeyCompose, 0x006f, 0x007e, 0, // otilde,         o,          asciitilde
00319     0x00b6, kKeyCompose, 0x0070, 0x0021, 0, // paragraph,      p,          exclam
00320     0x00b7, kKeyCompose, 0x002e, 0x002e, 0, // periodcentered, period,     period
00321     0x00b1, kKeyCompose, 0x002b, 0x002d, 0, // plusminus,      plus,       minus
00322     0x00bf, kKeyCompose, 0x003f, 0x003f, 0, // questiondown,   question,   question
00323     0x00ae, kKeyCompose, 0x0028, 0x0072, 0, // registered,     parenleft,  r
00324     0x00a7, kKeyCompose, 0x0073, 0x006f, 0, // section,        s,          o
00325     0x00df, kKeyCompose, 0x0073, 0x0073, 0, // ssharp,         s,          s
00326     0x00a3, kKeyCompose, 0x004c, 0x002d, 0, // sterling,       L,          minus
00327     0x00fe, kKeyCompose, 0x0074, 0x0068, 0, // thorn,          t,          h
00328     0x00be, kKeyCompose, 0x0033, 0x0034, 0, // threequarters,  3,          4
00329     0x00b3, kKeyCompose, 0x0033, 0x0053, 0, // threesuperior,  3,          asciicircum
00330     0x00b2, kKeyCompose, 0x0032, 0x0053, 0, // twosuperior,    2,          asciicircum
00331     0x00fa, kKeyCompose, 0x0075, 0x0027, 0, // uacute,         u,          apostrophe
00332     0x00fb, kKeyCompose, 0x0075, 0x0053, 0, // ucircumflex,    u,          asciicircum
00333     0x00fc, kKeyCompose, 0x0075, 0x0022, 0, // udiaeresis,     u,          quotedbl
00334     0x00f9, kKeyCompose, 0x0075, 0x0060, 0, // ugrave,         u,          grave
00335     0x00fd, kKeyCompose, 0x0079, 0x0027, 0, // yacute,         y,          apostrophe
00336     0x00ff, kKeyCompose, 0x0079, 0x0022, 0, // ydiaeresis,     y,          quotedbl
00337     0x00a5, kKeyCompose, 0x0079, 0x003d, 0, // yen,            y,          equal
00338 
00339     // end of table
00340     0
00341 };
00342 
00343 static const KeyID s_numpadTable[] = {
00344     kKeyKP_Space,       0x0020,
00345     kKeyKP_Tab,         kKeyTab,
00346     kKeyKP_Enter,       kKeyReturn,
00347     kKeyKP_F1,          kKeyF1,
00348     kKeyKP_F2,          kKeyF2,
00349     kKeyKP_F3,          kKeyF3,
00350     kKeyKP_F4,          kKeyF4,
00351     kKeyKP_Home,        kKeyHome,
00352     kKeyKP_Left,        kKeyLeft,
00353     kKeyKP_Up,          kKeyUp,
00354     kKeyKP_Right,       kKeyRight,
00355     kKeyKP_Down,        kKeyDown,
00356     kKeyKP_PageUp,      kKeyPageUp,
00357     kKeyKP_PageDown,    kKeyPageDown,
00358     kKeyKP_End,         kKeyEnd,
00359     kKeyKP_Begin,       kKeyBegin,
00360     kKeyKP_Insert,      kKeyInsert,
00361     kKeyKP_Delete,      kKeyDelete,
00362     kKeyKP_Equal,       0x003d,
00363     kKeyKP_Multiply,    0x002a,
00364     kKeyKP_Add,         0x002b,
00365     kKeyKP_Separator,   0x002c,
00366     kKeyKP_Subtract,    0x002d,
00367     kKeyKP_Decimal,     0x002e,
00368     kKeyKP_Divide,      0x002f,
00369     kKeyKP_0,           0x0030,
00370     kKeyKP_1,           0x0031,
00371     kKeyKP_2,           0x0032,
00372     kKeyKP_3,           0x0033,
00373     kKeyKP_4,           0x0034,
00374     kKeyKP_5,           0x0035,
00375     kKeyKP_6,           0x0036,
00376     kKeyKP_7,           0x0037,
00377     kKeyKP_8,           0x0038,
00378     kKeyKP_9,           0x0039
00379 };
00380 
00381 //
00382 // CKeyState
00383 //
00384 
00385 CKeyState::CKeyState() :
00386     IKeyState(),
00387     m_mask(0),
00388     m_keyMapPtr(new CKeyMap()),
00389     m_keyMap(*m_keyMapPtr)
00390 {
00391     init();
00392 }
00393 
00394 CKeyState::CKeyState(IEventQueue& eventQueue, CKeyMap& keyMap) :
00395     IKeyState(eventQueue),
00396     m_mask(0),
00397     m_keyMapPtr(0),
00398     m_keyMap(keyMap)
00399 {
00400     init();
00401 }
00402 
00403 CKeyState::~CKeyState()
00404 {
00405     if (m_keyMapPtr)
00406         delete m_keyMapPtr;
00407 }
00408 
00409 void
00410 CKeyState::init()
00411 {
00412     memset(&m_keys, 0, sizeof(m_keys));
00413     memset(&m_syntheticKeys, 0, sizeof(m_syntheticKeys));
00414     memset(&m_keyClientData, 0, sizeof(m_keyClientData));
00415     memset(&m_serverKeys, 0, sizeof(m_serverKeys));
00416 }
00417 
00418 void
00419 CKeyState::onKey(KeyButton button, bool down, KeyModifierMask newState)
00420 {
00421     // update modifier state
00422     m_mask = newState;
00423     LOG((CLOG_DEBUG1 "new mask: 0x%04x", m_mask));
00424 
00425     // ignore bogus buttons
00426     button &= kButtonMask;
00427     if (button == 0) {
00428         return;
00429     }
00430 
00431     // update key state
00432     if (down) {
00433         m_keys[button]          = 1;
00434         m_syntheticKeys[button] = 1;
00435     }
00436     else {
00437         m_keys[button]          = 0;
00438         m_syntheticKeys[button] = 0;
00439     }
00440 }
00441 
00442 void
00443 CKeyState::sendKeyEvent(
00444                 void* target, bool press, bool isAutoRepeat,
00445                 KeyID key, KeyModifierMask mask,
00446                 SInt32 count, KeyButton button)
00447 {
00448     if (m_keyMap.isHalfDuplex(key, button)) {
00449         if (isAutoRepeat) {
00450             // ignore auto-repeat on half-duplex keys
00451         }
00452         else {
00453             getEventQueue().addEvent(CEvent(getKeyDownEvent(), target,
00454                             CKeyInfo::alloc(key, mask, button, 1)));
00455             getEventQueue().addEvent(CEvent(getKeyUpEvent(), target,
00456                             CKeyInfo::alloc(key, mask, button, 1)));
00457         }
00458     }
00459     else {
00460         if (isAutoRepeat) {
00461             getEventQueue().addEvent(CEvent(getKeyRepeatEvent(), target,
00462                              CKeyInfo::alloc(key, mask, button, count)));
00463         }
00464         else if (press) {
00465             getEventQueue().addEvent(CEvent(getKeyDownEvent(), target,
00466                             CKeyInfo::alloc(key, mask, button, 1)));
00467         }
00468         else {
00469             getEventQueue().addEvent(CEvent(getKeyUpEvent(), target,
00470                             CKeyInfo::alloc(key, mask, button, 1)));
00471         }
00472     }
00473 }
00474 
00475 void
00476 CKeyState::updateKeyMap()
00477 {
00478     // get the current keyboard map
00479     CKeyMap keyMap;
00480     getKeyMap(keyMap);
00481     m_keyMap.swap(keyMap);
00482     m_keyMap.finish();
00483 
00484     // add special keys
00485     addCombinationEntries();
00486     addKeypadEntries();
00487     addAliasEntries();
00488 }
00489 
00490 void
00491 CKeyState::updateKeyState()
00492 {
00493     // reset our state
00494     memset(&m_keys, 0, sizeof(m_keys));
00495     memset(&m_syntheticKeys, 0, sizeof(m_syntheticKeys));
00496     memset(&m_keyClientData, 0, sizeof(m_keyClientData));
00497     memset(&m_serverKeys, 0, sizeof(m_serverKeys));
00498     m_activeModifiers.clear();
00499 
00500     // get the current keyboard state
00501     KeyButtonSet keysDown;
00502     pollPressedKeys(keysDown);
00503     for (KeyButtonSet::const_iterator i = keysDown.begin();
00504                                 i != keysDown.end(); ++i) {
00505         m_keys[*i] = 1;
00506     }
00507 
00508     // get the current modifier state
00509     m_mask = pollActiveModifiers();
00510 
00511     // set active modifiers
00512     CAddActiveModifierContext addModifierContext(pollActiveGroup(), m_mask,
00513                                                 m_activeModifiers);
00514     m_keyMap.foreachKey(&CKeyState::addActiveModifierCB, &addModifierContext);
00515 
00516     LOG((CLOG_DEBUG1 "modifiers on update: 0x%04x", m_mask));
00517 }
00518 
00519 void
00520 CKeyState::addActiveModifierCB(KeyID, SInt32 group,
00521                 CKeyMap::KeyItem& keyItem, void* vcontext)
00522 {
00523     CAddActiveModifierContext* context =
00524         reinterpret_cast<CAddActiveModifierContext*>(vcontext);
00525     if (group == context->m_activeGroup &&
00526         (keyItem.m_generates & context->m_mask) != 0) {
00527         context->m_activeModifiers.insert(std::make_pair(
00528                                 keyItem.m_generates, keyItem));
00529     }   
00530 }
00531 
00532 void
00533 CKeyState::setHalfDuplexMask(KeyModifierMask mask)
00534 {
00535     m_keyMap.clearHalfDuplexModifiers();
00536     if ((mask & KeyModifierCapsLock) != 0) {
00537         m_keyMap.addHalfDuplexModifier(kKeyCapsLock);
00538     }
00539     if ((mask & KeyModifierNumLock) != 0) {
00540         m_keyMap.addHalfDuplexModifier(kKeyNumLock);
00541     }
00542     if ((mask & KeyModifierScrollLock) != 0) {
00543         m_keyMap.addHalfDuplexModifier(kKeyScrollLock);
00544     }
00545 }
00546 
00547 void
00548 CKeyState::fakeKeyDown(KeyID id, KeyModifierMask mask, KeyButton serverID)
00549 {
00550     // if this server key is already down then this is probably a
00551     // mis-reported autorepeat.
00552     serverID &= kButtonMask;
00553     if (m_serverKeys[serverID] != 0) {
00554         fakeKeyRepeat(id, mask, 1, serverID);
00555         return;
00556     }
00557 
00558     // ignore certain keys
00559     if (isIgnoredKey(id, mask)) {
00560         LOG((CLOG_DEBUG1 "ignored key %04x %04x", id, mask));
00561         return;
00562     }
00563 
00564     // get keys for key press
00565     Keystrokes keys;
00566     ModifierToKeys oldActiveModifiers = m_activeModifiers;
00567     const CKeyMap::KeyItem* keyItem =
00568         m_keyMap.mapKey(keys, id, pollActiveGroup(), m_activeModifiers,
00569                                 getActiveModifiersRValue(), mask, false);
00570     if (keyItem == NULL) {
00571         return;
00572     }
00573     KeyButton localID = (KeyButton)(keyItem->m_button & kButtonMask);
00574     updateModifierKeyState(localID, oldActiveModifiers, m_activeModifiers);
00575     if (localID != 0) {
00576         // note keys down
00577         ++m_keys[localID];
00578         ++m_syntheticKeys[localID];
00579         m_keyClientData[localID] = keyItem->m_client;
00580         m_serverKeys[serverID]   = localID;
00581     }
00582 
00583     // generate key events
00584     fakeKeys(keys, 1);
00585 }
00586 
00587 bool
00588 CKeyState::fakeKeyRepeat(
00589                 KeyID id, KeyModifierMask mask,
00590                 SInt32 count, KeyButton serverID)
00591 {
00592     serverID &= kButtonMask;
00593 
00594     // if we haven't seen this button go down then ignore it
00595     KeyButton oldLocalID = m_serverKeys[serverID];
00596     if (oldLocalID == 0) {
00597         return false;
00598     }
00599 
00600     // get keys for key repeat
00601     Keystrokes keys;
00602     ModifierToKeys oldActiveModifiers = m_activeModifiers;
00603     const CKeyMap::KeyItem* keyItem =
00604         m_keyMap.mapKey(keys, id, pollActiveGroup(), m_activeModifiers,
00605                                 getActiveModifiersRValue(), mask, true);
00606     if (keyItem == NULL) {
00607         return false;
00608     }
00609     KeyButton localID = (KeyButton)(keyItem->m_button & kButtonMask);
00610     if (localID == 0) {
00611         return false;
00612     }
00613 
00614     // if the KeyButton for the auto-repeat is not the same as for the
00615     // initial press then mark the initial key as released and the new
00616     // key as pressed.  this can happen when we auto-repeat after a
00617     // dead key.  for example, a dead accent followed by 'a' will
00618     // generate an 'a with accent' followed by a repeating 'a'.  the
00619     // KeyButtons for the two KeyIDs might be different.
00620     if (localID != oldLocalID) {
00621         // replace key up with previous KeyButton but leave key down
00622         // alone so it uses the new KeyButton.
00623         for (Keystrokes::iterator index = keys.begin();
00624                                 index != keys.end(); ++index) {
00625             if (index->m_type == Keystroke::kButton &&
00626                 index->m_data.m_button.m_button == localID) {
00627                 index->m_data.m_button.m_button = oldLocalID;
00628                 break;
00629             }
00630         }
00631 
00632         // note that old key is now up
00633         --m_keys[oldLocalID];
00634         --m_syntheticKeys[oldLocalID];
00635 
00636         // note keys down
00637         updateModifierKeyState(localID, oldActiveModifiers, m_activeModifiers);
00638         ++m_keys[localID];
00639         ++m_syntheticKeys[localID];
00640         m_keyClientData[localID] = keyItem->m_client;
00641         m_serverKeys[serverID]   = localID;
00642     }
00643 
00644     // generate key events
00645     fakeKeys(keys, count);
00646     return true;
00647 }
00648 
00649 bool
00650 CKeyState::fakeKeyUp(KeyButton serverID)
00651 {
00652     // if we haven't seen this button go down then ignore it
00653     KeyButton localID = m_serverKeys[serverID & kButtonMask];
00654     if (localID == 0) {
00655         return false;
00656     }
00657 
00658     // get the sequence of keys to simulate key release
00659     Keystrokes keys;
00660     keys.push_back(Keystroke(localID, false, false, m_keyClientData[localID]));
00661 
00662     // note keys down
00663     --m_keys[localID];
00664     --m_syntheticKeys[localID];
00665     m_serverKeys[serverID] = 0;
00666 
00667     // check if this is a modifier
00668     ModifierToKeys::iterator i = m_activeModifiers.begin();
00669     while (i != m_activeModifiers.end()) {
00670         if (i->second.m_button == localID && !i->second.m_lock) {
00671             // modifier is no longer down
00672             KeyModifierMask mask = i->first;
00673 
00674             ModifierToKeys::iterator tmp = i;
00675             ++i;
00676             m_activeModifiers.erase(tmp);
00677 
00678             if (m_activeModifiers.count(mask) == 0) {
00679                 // no key for modifier is down so deactivate modifier
00680                 m_mask &= ~mask;
00681                 LOG((CLOG_DEBUG1 "new state %04x", m_mask));
00682             }
00683         }
00684         else {
00685             ++i;
00686         }
00687     }
00688 
00689     // generate key events
00690     fakeKeys(keys, 1);
00691     return true;
00692 }
00693 
00694 void
00695 CKeyState::fakeAllKeysUp()
00696 {
00697     Keystrokes keys;
00698     for (KeyButton i = 0; i < IKeyState::kNumButtons; ++i) {
00699         if (m_syntheticKeys[i] > 0) {
00700             keys.push_back(Keystroke(i, false, false, m_keyClientData[i]));
00701             m_keys[i]          = 0;
00702             m_syntheticKeys[i] = 0;
00703         }
00704     }
00705     fakeKeys(keys, 1);
00706     memset(&m_serverKeys, 0, sizeof(m_serverKeys));
00707     m_activeModifiers.clear();
00708     m_mask = pollActiveModifiers();
00709 }
00710 
00711 bool
00712 CKeyState::isKeyDown(KeyButton button) const
00713 {
00714     return (m_keys[button & kButtonMask] > 0);
00715 }
00716 
00717 KeyModifierMask
00718 CKeyState::getActiveModifiers() const
00719 {
00720     return m_mask;
00721 }
00722 
00723 KeyModifierMask&
00724 CKeyState::getActiveModifiersRValue()
00725 {
00726     return m_mask;
00727 }
00728 
00729 SInt32
00730 CKeyState::getEffectiveGroup(SInt32 group, SInt32 offset) const
00731 {
00732     return m_keyMap.getEffectiveGroup(group, offset);
00733 }
00734 
00735 bool
00736 CKeyState::isIgnoredKey(KeyID key, KeyModifierMask) const
00737 {
00738     switch (key) {
00739     case kKeyCapsLock:
00740     case kKeyNumLock:
00741     case kKeyScrollLock:
00742         return true;
00743 
00744     default:
00745         return false;
00746     }
00747 }
00748 
00749 KeyButton
00750 CKeyState::getButton(KeyID id, SInt32 group) const
00751 {
00752     const CKeyMap::KeyItemList* items =
00753         m_keyMap.findCompatibleKey(id, group, 0, 0);
00754     if (items == NULL) {
00755         return 0;
00756     }
00757     else {
00758         return items->back().m_button;
00759     }
00760 }
00761 
00762 void
00763 CKeyState::addAliasEntries()
00764 {
00765     for (SInt32 g = 0, n = m_keyMap.getNumGroups(); g < n; ++g) {
00766         // if we can't shift any kKeyTab key in a particular group but we can
00767         // shift kKeyLeftTab then add a shifted kKeyTab entry that matches a
00768         // shifted kKeyLeftTab entry.
00769         m_keyMap.addKeyAliasEntry(kKeyTab, g,
00770                                 KeyModifierShift, KeyModifierShift,
00771                                 kKeyLeftTab,
00772                                 KeyModifierShift, KeyModifierShift);
00773 
00774         // if we have no kKeyLeftTab but we do have a kKeyTab that can be
00775         // shifted then add kKeyLeftTab that matches a kKeyTab.
00776         m_keyMap.addKeyAliasEntry(kKeyLeftTab, g,
00777                                 KeyModifierShift, KeyModifierShift,
00778                                 kKeyTab,
00779                                 0, KeyModifierShift);
00780 
00781         // map non-breaking space to space
00782         m_keyMap.addKeyAliasEntry(0x20, g, 0, 0, 0xa0, 0, 0);
00783     }
00784 }
00785 
00786 void
00787 CKeyState::addKeypadEntries()
00788 {
00789     // map every numpad key to its equivalent non-numpad key if it's not
00790     // on the keyboard.
00791     for (SInt32 g = 0, n = m_keyMap.getNumGroups(); g < n; ++g) {
00792         for (size_t i = 0; i < sizeof(s_numpadTable) /
00793                                 sizeof(s_numpadTable[0]); i += 2) {
00794             m_keyMap.addKeyCombinationEntry(s_numpadTable[i], g,
00795                                 s_numpadTable + i + 1, 1);
00796         }
00797     }
00798 }
00799 
00800 void
00801 CKeyState::addCombinationEntries()
00802 {
00803     for (SInt32 g = 0, n = m_keyMap.getNumGroups(); g < n; ++g) {
00804         // add dead and compose key composition sequences
00805         for (const KeyID* i = s_decomposeTable; *i != 0; ++i) {
00806             // count the decomposed keys for this key
00807             UInt32 numKeys = 0;
00808             for (const KeyID* j = i; *++j != 0; ) {
00809                 ++numKeys;
00810             }
00811 
00812             // add an entry for this key
00813             m_keyMap.addKeyCombinationEntry(*i, g, i + 1, numKeys);
00814 
00815             // next key
00816             i += numKeys + 1;
00817         }
00818     }
00819 }
00820 
00821 void
00822 CKeyState::fakeKeys(const Keystrokes& keys, UInt32 count)
00823 {
00824     // do nothing if no keys or no repeats
00825     if (count == 0 || keys.empty()) {
00826         return;
00827     }
00828 
00829     // generate key events
00830     LOG((CLOG_DEBUG1 "keystrokes:"));
00831     for (Keystrokes::const_iterator k = keys.begin(); k != keys.end(); ) {
00832         if (k->m_type == Keystroke::kButton && k->m_data.m_button.m_repeat) {
00833             // repeat from here up to but not including the next key
00834             // with m_repeat == false count times.
00835             Keystrokes::const_iterator start = k;
00836             while (count-- > 0) {
00837                 // send repeating events
00838                 for (k = start; k != keys.end() &&
00839                                 k->m_type == Keystroke::kButton &&
00840                                 k->m_data.m_button.m_repeat; ++k) {
00841                     fakeKey(*k);
00842                 }
00843             }
00844 
00845             // note -- k is now on the first non-repeat key after the
00846             // repeat keys, exactly where we'd like to continue from.
00847         }
00848         else {
00849             // send event
00850             fakeKey(*k);
00851 
00852             // next key
00853             ++k;
00854         }
00855     }
00856 }
00857 
00858 void
00859 CKeyState::updateModifierKeyState(KeyButton button,
00860                 const ModifierToKeys& oldModifiers,
00861                 const ModifierToKeys& newModifiers)
00862 {
00863     // get the pressed modifier buttons before and after
00864     CKeyMap::ButtonToKeyMap oldKeys, newKeys;
00865     for (ModifierToKeys::const_iterator i = oldModifiers.begin();
00866                                 i != oldModifiers.end(); ++i) {
00867         oldKeys.insert(std::make_pair(i->second.m_button, &i->second));
00868     }
00869     for (ModifierToKeys::const_iterator i = newModifiers.begin();
00870                                 i != newModifiers.end(); ++i) {
00871         newKeys.insert(std::make_pair(i->second.m_button, &i->second));
00872     }
00873 
00874     // get the modifier buttons that were pressed or released
00875     CKeyMap::ButtonToKeyMap pressed, released;
00876     std::set_difference(oldKeys.begin(), oldKeys.end(),
00877                         newKeys.begin(), newKeys.end(),
00878                         std::inserter(released, released.end()),
00879                         ButtonToKeyLess());
00880     std::set_difference(newKeys.begin(), newKeys.end(),
00881                         oldKeys.begin(), oldKeys.end(),
00882                         std::inserter(pressed, pressed.end()),
00883                         ButtonToKeyLess());
00884 
00885     // update state
00886     for (CKeyMap::ButtonToKeyMap::const_iterator i = released.begin();
00887                                 i != released.end(); ++i) {
00888         if (i->first != button) {
00889             m_keys[i->first]          = 0;
00890             m_syntheticKeys[i->first] = 0;
00891         }
00892     }
00893     for (CKeyMap::ButtonToKeyMap::const_iterator i = pressed.begin();
00894                                 i != pressed.end(); ++i) {
00895         if (i->first != button) {
00896             m_keys[i->first]          = 1;
00897             m_syntheticKeys[i->first] = 1;
00898             m_keyClientData[i->first] = i->second->m_client;
00899         }
00900     }
00901 }
00902 
00903 
00904 //
00905 // CKeyState::CAddActiveModifierContext
00906 //
00907 
00908 CKeyState::CAddActiveModifierContext::CAddActiveModifierContext(
00909                 SInt32 group, KeyModifierMask mask,
00910                 ModifierToKeys& activeModifiers) :
00911     m_activeGroup(group),
00912     m_mask(mask),
00913     m_activeModifiers(activeModifiers)
00914 {
00915     // do nothing
00916 }

Generated on Tue May 21 2013 00:00:05 for Synergy by  doxygen 1.7.1