Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

CKeyState.cpp

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

Generated on Fri Nov 6 00:21:14 2009 for synergy-plus by  doxygen 1.3.9.1