• Main Page
  • Classes
  • Files
  • File List

CMSWindowsKeyState.cpp

00001 /*
00002  * synergy -- mouse and keyboard sharing utility
00003  * Copyright (C) 2012 Bolton Software Ltd.
00004  * Copyright (C) 2003 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 "CMSWindowsKeyState.h"
00020 #include "CMSWindowsDesks.h"
00021 #include "CThread.h"
00022 #include "CFunctionJob.h"
00023 #include "CLog.h"
00024 #include "CStringUtil.h"
00025 #include "IEventQueue.h"
00026 #include "TMethodEventJob.h"
00027 #include "CArchMiscWindows.h"
00028 
00029 // extended mouse buttons
00030 #if !defined(VK_XBUTTON1)
00031 #define VK_XBUTTON1             0x05
00032 #define VK_XBUTTON2             0x06
00033 #endif
00034 
00035 //
00036 // CMSWindowsKeyState
00037 //
00038 
00039 // map virtual keys to synergy key enumeration
00040 const KeyID             CMSWindowsKeyState::s_virtualKey[] =
00041 {
00042     /* 0x000 */ { kKeyNone },       // reserved
00043     /* 0x001 */ { kKeyNone },       // VK_LBUTTON
00044     /* 0x002 */ { kKeyNone },       // VK_RBUTTON
00045     /* 0x003 */ { kKeyNone },       // VK_CANCEL
00046     /* 0x004 */ { kKeyNone },       // VK_MBUTTON
00047     /* 0x005 */ { kKeyNone },       // VK_XBUTTON1
00048     /* 0x006 */ { kKeyNone },       // VK_XBUTTON2
00049     /* 0x007 */ { kKeyNone },       // undefined
00050     /* 0x008 */ { kKeyBackSpace },  // VK_BACK
00051     /* 0x009 */ { kKeyTab },        // VK_TAB
00052     /* 0x00a */ { kKeyNone },       // undefined
00053     /* 0x00b */ { kKeyNone },       // undefined
00054     /* 0x00c */ { kKeyClear },      // VK_CLEAR
00055     /* 0x00d */ { kKeyReturn },     // VK_RETURN
00056     /* 0x00e */ { kKeyNone },       // undefined
00057     /* 0x00f */ { kKeyNone },       // undefined
00058     /* 0x010 */ { kKeyShift_L },    // VK_SHIFT
00059     /* 0x011 */ { kKeyControl_L },  // VK_CONTROL
00060     /* 0x012 */ { kKeyAlt_L },      // VK_MENU
00061     /* 0x013 */ { kKeyPause },      // VK_PAUSE
00062     /* 0x014 */ { kKeyCapsLock },   // VK_CAPITAL
00063     /* 0x015 */ { kKeyHangulKana }, // VK_HANGUL, VK_KANA
00064     /* 0x016 */ { kKeyNone },       // undefined
00065     /* 0x017 */ { kKeyNone },       // VK_JUNJA
00066     /* 0x018 */ { kKeyNone },       // VK_FINAL
00067     /* 0x019 */ { kKeyHanjaKanzi }, // VK_KANJI
00068     /* 0x01a */ { kKeyNone },       // undefined
00069     /* 0x01b */ { kKeyEscape },     // VK_ESCAPE
00070     /* 0x01c */ { kKeyHenkan },     // VK_CONVERT       
00071     /* 0x01d */ { kKeyNone },       // VK_NONCONVERT    
00072     /* 0x01e */ { kKeyNone },       // VK_ACCEPT        
00073     /* 0x01f */ { kKeyNone },       // VK_MODECHANGE    
00074     /* 0x020 */ { kKeyNone },       // VK_SPACE
00075     /* 0x021 */ { kKeyKP_PageUp },  // VK_PRIOR
00076     /* 0x022 */ { kKeyKP_PageDown },// VK_NEXT
00077     /* 0x023 */ { kKeyKP_End },     // VK_END
00078     /* 0x024 */ { kKeyKP_Home },    // VK_HOME
00079     /* 0x025 */ { kKeyKP_Left },    // VK_LEFT
00080     /* 0x026 */ { kKeyKP_Up },      // VK_UP
00081     /* 0x027 */ { kKeyKP_Right },   // VK_RIGHT
00082     /* 0x028 */ { kKeyKP_Down },    // VK_DOWN
00083     /* 0x029 */ { kKeySelect },     // VK_SELECT
00084     /* 0x02a */ { kKeyNone },       // VK_PRINT
00085     /* 0x02b */ { kKeyExecute },    // VK_EXECUTE
00086     /* 0x02c */ { kKeyPrint },      // VK_SNAPSHOT
00087     /* 0x02d */ { kKeyKP_Insert },  // VK_INSERT
00088     /* 0x02e */ { kKeyKP_Delete },  // VK_DELETE
00089     /* 0x02f */ { kKeyHelp },       // VK_HELP
00090     /* 0x030 */ { kKeyNone },       // VK_0
00091     /* 0x031 */ { kKeyNone },       // VK_1
00092     /* 0x032 */ { kKeyNone },       // VK_2
00093     /* 0x033 */ { kKeyNone },       // VK_3
00094     /* 0x034 */ { kKeyNone },       // VK_4
00095     /* 0x035 */ { kKeyNone },       // VK_5
00096     /* 0x036 */ { kKeyNone },       // VK_6
00097     /* 0x037 */ { kKeyNone },       // VK_7
00098     /* 0x038 */ { kKeyNone },       // VK_8
00099     /* 0x039 */ { kKeyNone },       // VK_9
00100     /* 0x03a */ { kKeyNone },       // undefined
00101     /* 0x03b */ { kKeyNone },       // undefined
00102     /* 0x03c */ { kKeyNone },       // undefined
00103     /* 0x03d */ { kKeyNone },       // undefined
00104     /* 0x03e */ { kKeyNone },       // undefined
00105     /* 0x03f */ { kKeyNone },       // undefined
00106     /* 0x040 */ { kKeyNone },       // undefined
00107     /* 0x041 */ { kKeyNone },       // VK_A
00108     /* 0x042 */ { kKeyNone },       // VK_B
00109     /* 0x043 */ { kKeyNone },       // VK_C
00110     /* 0x044 */ { kKeyNone },       // VK_D
00111     /* 0x045 */ { kKeyNone },       // VK_E
00112     /* 0x046 */ { kKeyNone },       // VK_F
00113     /* 0x047 */ { kKeyNone },       // VK_G
00114     /* 0x048 */ { kKeyNone },       // VK_H
00115     /* 0x049 */ { kKeyNone },       // VK_I
00116     /* 0x04a */ { kKeyNone },       // VK_J
00117     /* 0x04b */ { kKeyNone },       // VK_K
00118     /* 0x04c */ { kKeyNone },       // VK_L
00119     /* 0x04d */ { kKeyNone },       // VK_M
00120     /* 0x04e */ { kKeyNone },       // VK_N
00121     /* 0x04f */ { kKeyNone },       // VK_O
00122     /* 0x050 */ { kKeyNone },       // VK_P
00123     /* 0x051 */ { kKeyNone },       // VK_Q
00124     /* 0x052 */ { kKeyNone },       // VK_R
00125     /* 0x053 */ { kKeyNone },       // VK_S
00126     /* 0x054 */ { kKeyNone },       // VK_T
00127     /* 0x055 */ { kKeyNone },       // VK_U
00128     /* 0x056 */ { kKeyNone },       // VK_V
00129     /* 0x057 */ { kKeyNone },       // VK_W
00130     /* 0x058 */ { kKeyNone },       // VK_X
00131     /* 0x059 */ { kKeyNone },       // VK_Y
00132     /* 0x05a */ { kKeyNone },       // VK_Z
00133     /* 0x05b */ { kKeySuper_L },    // VK_LWIN
00134     /* 0x05c */ { kKeySuper_R },    // VK_RWIN
00135     /* 0x05d */ { kKeyMenu },       // VK_APPS
00136     /* 0x05e */ { kKeyNone },       // undefined
00137     /* 0x05f */ { kKeySleep },      // VK_SLEEP
00138     /* 0x060 */ { kKeyKP_0 },       // VK_NUMPAD0
00139     /* 0x061 */ { kKeyKP_1 },       // VK_NUMPAD1
00140     /* 0x062 */ { kKeyKP_2 },       // VK_NUMPAD2
00141     /* 0x063 */ { kKeyKP_3 },       // VK_NUMPAD3
00142     /* 0x064 */ { kKeyKP_4 },       // VK_NUMPAD4
00143     /* 0x065 */ { kKeyKP_5 },       // VK_NUMPAD5
00144     /* 0x066 */ { kKeyKP_6 },       // VK_NUMPAD6
00145     /* 0x067 */ { kKeyKP_7 },       // VK_NUMPAD7
00146     /* 0x068 */ { kKeyKP_8 },       // VK_NUMPAD8
00147     /* 0x069 */ { kKeyKP_9 },       // VK_NUMPAD9
00148     /* 0x06a */ { kKeyKP_Multiply },// VK_MULTIPLY
00149     /* 0x06b */ { kKeyKP_Add },     // VK_ADD
00150     /* 0x06c */ { kKeyKP_Separator },// VK_SEPARATOR
00151     /* 0x06d */ { kKeyKP_Subtract },// VK_SUBTRACT
00152     /* 0x06e */ { kKeyKP_Decimal }, // VK_DECIMAL
00153     /* 0x06f */ { kKeyNone },       // VK_DIVIDE
00154     /* 0x070 */ { kKeyF1 },         // VK_F1
00155     /* 0x071 */ { kKeyF2 },         // VK_F2
00156     /* 0x072 */ { kKeyF3 },         // VK_F3
00157     /* 0x073 */ { kKeyF4 },         // VK_F4
00158     /* 0x074 */ { kKeyF5 },         // VK_F5
00159     /* 0x075 */ { kKeyF6 },         // VK_F6
00160     /* 0x076 */ { kKeyF7 },         // VK_F7
00161     /* 0x077 */ { kKeyF8 },         // VK_F8
00162     /* 0x078 */ { kKeyF9 },         // VK_F9
00163     /* 0x079 */ { kKeyF10 },        // VK_F10
00164     /* 0x07a */ { kKeyF11 },        // VK_F11
00165     /* 0x07b */ { kKeyF12 },        // VK_F12
00166     /* 0x07c */ { kKeyF13 },        // VK_F13
00167     /* 0x07d */ { kKeyF14 },        // VK_F14
00168     /* 0x07e */ { kKeyF15 },        // VK_F15
00169     /* 0x07f */ { kKeyF16 },        // VK_F16
00170     /* 0x080 */ { kKeyF17 },        // VK_F17
00171     /* 0x081 */ { kKeyF18 },        // VK_F18
00172     /* 0x082 */ { kKeyF19 },        // VK_F19
00173     /* 0x083 */ { kKeyF20 },        // VK_F20
00174     /* 0x084 */ { kKeyF21 },        // VK_F21
00175     /* 0x085 */ { kKeyF22 },        // VK_F22
00176     /* 0x086 */ { kKeyF23 },        // VK_F23
00177     /* 0x087 */ { kKeyF24 },        // VK_F24
00178     /* 0x088 */ { kKeyNone },       // unassigned
00179     /* 0x089 */ { kKeyNone },       // unassigned
00180     /* 0x08a */ { kKeyNone },       // unassigned
00181     /* 0x08b */ { kKeyNone },       // unassigned
00182     /* 0x08c */ { kKeyNone },       // unassigned
00183     /* 0x08d */ { kKeyNone },       // unassigned
00184     /* 0x08e */ { kKeyNone },       // unassigned
00185     /* 0x08f */ { kKeyNone },       // unassigned
00186     /* 0x090 */ { kKeyNumLock },    // VK_NUMLOCK
00187     /* 0x091 */ { kKeyScrollLock }, // VK_SCROLL
00188     /* 0x092 */ { kKeyNone },       // unassigned
00189     /* 0x093 */ { kKeyNone },       // unassigned
00190     /* 0x094 */ { kKeyNone },       // unassigned
00191     /* 0x095 */ { kKeyNone },       // unassigned
00192     /* 0x096 */ { kKeyNone },       // unassigned
00193     /* 0x097 */ { kKeyNone },       // unassigned
00194     /* 0x098 */ { kKeyNone },       // unassigned
00195     /* 0x099 */ { kKeyNone },       // unassigned
00196     /* 0x09a */ { kKeyNone },       // unassigned
00197     /* 0x09b */ { kKeyNone },       // unassigned
00198     /* 0x09c */ { kKeyNone },       // unassigned
00199     /* 0x09d */ { kKeyNone },       // unassigned
00200     /* 0x09e */ { kKeyNone },       // unassigned
00201     /* 0x09f */ { kKeyNone },       // unassigned
00202     /* 0x0a0 */ { kKeyShift_L },    // VK_LSHIFT
00203     /* 0x0a1 */ { kKeyShift_R },    // VK_RSHIFT
00204     /* 0x0a2 */ { kKeyControl_L },  // VK_LCONTROL
00205     /* 0x0a3 */ { kKeyControl_R },  // VK_RCONTROL
00206     /* 0x0a4 */ { kKeyAlt_L },      // VK_LMENU
00207     /* 0x0a5 */ { kKeyAlt_R },      // VK_RMENU
00208     /* 0x0a6 */ { kKeyNone },       // VK_BROWSER_BACK
00209     /* 0x0a7 */ { kKeyNone },       // VK_BROWSER_FORWARD
00210     /* 0x0a8 */ { kKeyNone },       // VK_BROWSER_REFRESH
00211     /* 0x0a9 */ { kKeyNone },       // VK_BROWSER_STOP
00212     /* 0x0aa */ { kKeyNone },       // VK_BROWSER_SEARCH
00213     /* 0x0ab */ { kKeyNone },       // VK_BROWSER_FAVORITES
00214     /* 0x0ac */ { kKeyNone },       // VK_BROWSER_HOME
00215     /* 0x0ad */ { kKeyNone },       // VK_VOLUME_MUTE
00216     /* 0x0ae */ { kKeyNone },       // VK_VOLUME_DOWN
00217     /* 0x0af */ { kKeyNone },       // VK_VOLUME_UP
00218     /* 0x0b0 */ { kKeyNone },       // VK_MEDIA_NEXT_TRACK
00219     /* 0x0b1 */ { kKeyNone },       // VK_MEDIA_PREV_TRACK
00220     /* 0x0b2 */ { kKeyNone },       // VK_MEDIA_STOP
00221     /* 0x0b3 */ { kKeyNone },       // VK_MEDIA_PLAY_PAUSE
00222     /* 0x0b4 */ { kKeyNone },       // VK_LAUNCH_MAIL
00223     /* 0x0b5 */ { kKeyNone },       // VK_LAUNCH_MEDIA_SELECT
00224     /* 0x0b6 */ { kKeyNone },       // VK_LAUNCH_APP1
00225     /* 0x0b7 */ { kKeyNone },       // VK_LAUNCH_APP2
00226     /* 0x0b8 */ { kKeyNone },       // unassigned
00227     /* 0x0b9 */ { kKeyNone },       // unassigned
00228     /* 0x0ba */ { kKeyNone },       // OEM specific
00229     /* 0x0bb */ { kKeyNone },       // OEM specific
00230     /* 0x0bc */ { kKeyNone },       // OEM specific
00231     /* 0x0bd */ { kKeyNone },       // OEM specific
00232     /* 0x0be */ { kKeyNone },       // OEM specific
00233     /* 0x0bf */ { kKeyNone },       // OEM specific
00234     /* 0x0c0 */ { kKeyNone },       // OEM specific
00235     /* 0x0c1 */ { kKeyNone },       // unassigned
00236     /* 0x0c2 */ { kKeyNone },       // unassigned
00237     /* 0x0c3 */ { kKeyNone },       // unassigned
00238     /* 0x0c4 */ { kKeyNone },       // unassigned
00239     /* 0x0c5 */ { kKeyNone },       // unassigned
00240     /* 0x0c6 */ { kKeyNone },       // unassigned
00241     /* 0x0c7 */ { kKeyNone },       // unassigned
00242     /* 0x0c8 */ { kKeyNone },       // unassigned
00243     /* 0x0c9 */ { kKeyNone },       // unassigned
00244     /* 0x0ca */ { kKeyNone },       // unassigned
00245     /* 0x0cb */ { kKeyNone },       // unassigned
00246     /* 0x0cc */ { kKeyNone },       // unassigned
00247     /* 0x0cd */ { kKeyNone },       // unassigned
00248     /* 0x0ce */ { kKeyNone },       // unassigned
00249     /* 0x0cf */ { kKeyNone },       // unassigned
00250     /* 0x0d0 */ { kKeyNone },       // unassigned
00251     /* 0x0d1 */ { kKeyNone },       // unassigned
00252     /* 0x0d2 */ { kKeyNone },       // unassigned
00253     /* 0x0d3 */ { kKeyNone },       // unassigned
00254     /* 0x0d4 */ { kKeyNone },       // unassigned
00255     /* 0x0d5 */ { kKeyNone },       // unassigned
00256     /* 0x0d6 */ { kKeyNone },       // unassigned
00257     /* 0x0d7 */ { kKeyNone },       // unassigned
00258     /* 0x0d8 */ { kKeyNone },       // unassigned
00259     /* 0x0d9 */ { kKeyNone },       // unassigned
00260     /* 0x0da */ { kKeyNone },       // unassigned
00261     /* 0x0db */ { kKeyNone },       // OEM specific
00262     /* 0x0dc */ { kKeyNone },       // OEM specific
00263     /* 0x0dd */ { kKeyNone },       // OEM specific
00264     /* 0x0de */ { kKeyNone },       // OEM specific
00265     /* 0x0df */ { kKeyNone },       // OEM specific
00266     /* 0x0e0 */ { kKeyNone },       // OEM specific
00267     /* 0x0e1 */ { kKeyNone },       // OEM specific
00268     /* 0x0e2 */ { kKeyNone },       // OEM specific
00269     /* 0x0e3 */ { kKeyNone },       // OEM specific
00270     /* 0x0e4 */ { kKeyNone },       // OEM specific
00271     /* 0x0e5 */ { kKeyNone },       // unassigned
00272     /* 0x0e6 */ { kKeyNone },       // OEM specific
00273     /* 0x0e7 */ { kKeyNone },       // unassigned
00274     /* 0x0e8 */ { kKeyNone },       // unassigned
00275     /* 0x0e9 */ { kKeyNone },       // OEM specific
00276     /* 0x0ea */ { kKeyNone },       // OEM specific
00277     /* 0x0eb */ { kKeyNone },       // OEM specific
00278     /* 0x0ec */ { kKeyNone },       // OEM specific
00279     /* 0x0ed */ { kKeyNone },       // OEM specific
00280     /* 0x0ee */ { kKeyNone },       // OEM specific
00281     /* 0x0ef */ { kKeyNone },       // OEM specific
00282     /* 0x0f0 */ { kKeyNone },       // OEM specific
00283     /* 0x0f1 */ { kKeyNone },       // OEM specific
00284     /* 0x0f2 */ { kKeyHiraganaKatakana },   // VK_OEM_COPY
00285     /* 0x0f3 */ { kKeyZenkaku },    // VK_OEM_AUTO
00286     /* 0x0f4 */ { kKeyZenkaku },    // VK_OEM_ENLW
00287     /* 0x0f5 */ { kKeyNone },       // OEM specific
00288     /* 0x0f6 */ { kKeyNone },       // VK_ATTN          
00289     /* 0x0f7 */ { kKeyNone },       // VK_CRSEL         
00290     /* 0x0f8 */ { kKeyNone },       // VK_EXSEL         
00291     /* 0x0f9 */ { kKeyNone },       // VK_EREOF         
00292     /* 0x0fa */ { kKeyNone },       // VK_PLAY          
00293     /* 0x0fb */ { kKeyNone },       // VK_ZOOM          
00294     /* 0x0fc */ { kKeyNone },       // reserved
00295     /* 0x0fd */ { kKeyNone },       // VK_PA1           
00296     /* 0x0fe */ { kKeyNone },       // VK_OEM_CLEAR     
00297     /* 0x0ff */ { kKeyNone },       // reserved
00298 
00299     /* 0x100 */ { kKeyNone },       // reserved
00300     /* 0x101 */ { kKeyNone },       // VK_LBUTTON
00301     /* 0x102 */ { kKeyNone },       // VK_RBUTTON
00302     /* 0x103 */ { kKeyBreak },      // VK_CANCEL
00303     /* 0x104 */ { kKeyNone },       // VK_MBUTTON
00304     /* 0x105 */ { kKeyNone },       // VK_XBUTTON1
00305     /* 0x106 */ { kKeyNone },       // VK_XBUTTON2
00306     /* 0x107 */ { kKeyNone },       // undefined
00307     /* 0x108 */ { kKeyNone },       // VK_BACK
00308     /* 0x109 */ { kKeyNone },       // VK_TAB
00309     /* 0x10a */ { kKeyNone },       // undefined
00310     /* 0x10b */ { kKeyNone },       // undefined
00311     /* 0x10c */ { kKeyClear },      // VK_CLEAR
00312     /* 0x10d */ { kKeyKP_Enter },   // VK_RETURN
00313     /* 0x10e */ { kKeyNone },       // undefined
00314     /* 0x10f */ { kKeyNone },       // undefined
00315     /* 0x110 */ { kKeyShift_R },    // VK_SHIFT
00316     /* 0x111 */ { kKeyControl_R },  // VK_CONTROL
00317     /* 0x112 */ { kKeyAlt_R },      // VK_MENU
00318     /* 0x113 */ { kKeyNone },       // VK_PAUSE
00319     /* 0x114 */ { kKeyNone },       // VK_CAPITAL
00320     /* 0x115 */ { kKeyNone },       // VK_KANA          
00321     /* 0x116 */ { kKeyNone },       // VK_HANGUL        
00322     /* 0x117 */ { kKeyNone },       // VK_JUNJA         
00323     /* 0x118 */ { kKeyNone },       // VK_FINAL         
00324     /* 0x119 */ { kKeyNone },       // VK_KANJI         
00325     /* 0x11a */ { kKeyNone },       // undefined
00326     /* 0x11b */ { kKeyNone },       // VK_ESCAPE
00327     /* 0x11c */ { kKeyNone },       // VK_CONVERT       
00328     /* 0x11d */ { kKeyNone },       // VK_NONCONVERT    
00329     /* 0x11e */ { kKeyNone },       // VK_ACCEPT        
00330     /* 0x11f */ { kKeyNone },       // VK_MODECHANGE    
00331     /* 0x120 */ { kKeyNone },       // VK_SPACE
00332     /* 0x121 */ { kKeyPageUp },     // VK_PRIOR
00333     /* 0x122 */ { kKeyPageDown },   // VK_NEXT
00334     /* 0x123 */ { kKeyEnd },        // VK_END
00335     /* 0x124 */ { kKeyHome },       // VK_HOME
00336     /* 0x125 */ { kKeyLeft },       // VK_LEFT
00337     /* 0x126 */ { kKeyUp },         // VK_UP
00338     /* 0x127 */ { kKeyRight },      // VK_RIGHT
00339     /* 0x128 */ { kKeyDown },       // VK_DOWN
00340     /* 0x129 */ { kKeySelect },     // VK_SELECT
00341     /* 0x12a */ { kKeyNone },       // VK_PRINT
00342     /* 0x12b */ { kKeyExecute },    // VK_EXECUTE
00343     /* 0x12c */ { kKeyPrint },      // VK_SNAPSHOT
00344     /* 0x12d */ { kKeyInsert },     // VK_INSERT
00345     /* 0x12e */ { kKeyDelete },     // VK_DELETE
00346     /* 0x12f */ { kKeyHelp },       // VK_HELP
00347     /* 0x130 */ { kKeyNone },       // VK_0
00348     /* 0x131 */ { kKeyNone },       // VK_1
00349     /* 0x132 */ { kKeyNone },       // VK_2
00350     /* 0x133 */ { kKeyNone },       // VK_3
00351     /* 0x134 */ { kKeyNone },       // VK_4
00352     /* 0x135 */ { kKeyNone },       // VK_5
00353     /* 0x136 */ { kKeyNone },       // VK_6
00354     /* 0x137 */ { kKeyNone },       // VK_7
00355     /* 0x138 */ { kKeyNone },       // VK_8
00356     /* 0x139 */ { kKeyNone },       // VK_9
00357     /* 0x13a */ { kKeyNone },       // undefined
00358     /* 0x13b */ { kKeyNone },       // undefined
00359     /* 0x13c */ { kKeyNone },       // undefined
00360     /* 0x13d */ { kKeyNone },       // undefined
00361     /* 0x13e */ { kKeyNone },       // undefined
00362     /* 0x13f */ { kKeyNone },       // undefined
00363     /* 0x140 */ { kKeyNone },       // undefined
00364     /* 0x141 */ { kKeyNone },       // VK_A
00365     /* 0x142 */ { kKeyNone },       // VK_B
00366     /* 0x143 */ { kKeyNone },       // VK_C
00367     /* 0x144 */ { kKeyNone },       // VK_D
00368     /* 0x145 */ { kKeyNone },       // VK_E
00369     /* 0x146 */ { kKeyNone },       // VK_F
00370     /* 0x147 */ { kKeyNone },       // VK_G
00371     /* 0x148 */ { kKeyNone },       // VK_H
00372     /* 0x149 */ { kKeyNone },       // VK_I
00373     /* 0x14a */ { kKeyNone },       // VK_J
00374     /* 0x14b */ { kKeyNone },       // VK_K
00375     /* 0x14c */ { kKeyNone },       // VK_L
00376     /* 0x14d */ { kKeyNone },       // VK_M
00377     /* 0x14e */ { kKeyNone },       // VK_N
00378     /* 0x14f */ { kKeyNone },       // VK_O
00379     /* 0x150 */ { kKeyNone },       // VK_P
00380     /* 0x151 */ { kKeyNone },       // VK_Q
00381     /* 0x152 */ { kKeyNone },       // VK_R
00382     /* 0x153 */ { kKeyNone },       // VK_S
00383     /* 0x154 */ { kKeyNone },       // VK_T
00384     /* 0x155 */ { kKeyNone },       // VK_U
00385     /* 0x156 */ { kKeyNone },       // VK_V
00386     /* 0x157 */ { kKeyNone },       // VK_W
00387     /* 0x158 */ { kKeyNone },       // VK_X
00388     /* 0x159 */ { kKeyNone },       // VK_Y
00389     /* 0x15a */ { kKeyNone },       // VK_Z
00390     /* 0x15b */ { kKeySuper_L },    // VK_LWIN
00391     /* 0x15c */ { kKeySuper_R },    // VK_RWIN
00392     /* 0x15d */ { kKeyMenu },       // VK_APPS
00393     /* 0x15e */ { kKeyNone },       // undefined
00394     /* 0x15f */ { kKeyNone },       // VK_SLEEP
00395     /* 0x160 */ { kKeyNone },       // VK_NUMPAD0
00396     /* 0x161 */ { kKeyNone },       // VK_NUMPAD1
00397     /* 0x162 */ { kKeyNone },       // VK_NUMPAD2
00398     /* 0x163 */ { kKeyNone },       // VK_NUMPAD3
00399     /* 0x164 */ { kKeyNone },       // VK_NUMPAD4
00400     /* 0x165 */ { kKeyNone },       // VK_NUMPAD5
00401     /* 0x166 */ { kKeyNone },       // VK_NUMPAD6
00402     /* 0x167 */ { kKeyNone },       // VK_NUMPAD7
00403     /* 0x168 */ { kKeyNone },       // VK_NUMPAD8
00404     /* 0x169 */ { kKeyNone },       // VK_NUMPAD9
00405     /* 0x16a */ { kKeyNone },       // VK_MULTIPLY
00406     /* 0x16b */ { kKeyNone },       // VK_ADD
00407     /* 0x16c */ { kKeyKP_Separator },// VK_SEPARATOR
00408     /* 0x16d */ { kKeyNone },       // VK_SUBTRACT
00409     /* 0x16e */ { kKeyNone },       // VK_DECIMAL
00410     /* 0x16f */ { kKeyKP_Divide },  // VK_DIVIDE
00411     /* 0x170 */ { kKeyNone },       // VK_F1
00412     /* 0x171 */ { kKeyNone },       // VK_F2
00413     /* 0x172 */ { kKeyNone },       // VK_F3
00414     /* 0x173 */ { kKeyNone },       // VK_F4
00415     /* 0x174 */ { kKeyNone },       // VK_F5
00416     /* 0x175 */ { kKeyNone },       // VK_F6
00417     /* 0x176 */ { kKeyNone },       // VK_F7
00418     /* 0x177 */ { kKeyNone },       // VK_F8
00419     /* 0x178 */ { kKeyNone },       // VK_F9
00420     /* 0x179 */ { kKeyNone },       // VK_F10
00421     /* 0x17a */ { kKeyNone },       // VK_F11
00422     /* 0x17b */ { kKeyNone },       // VK_F12
00423     /* 0x17c */ { kKeyF13 },        // VK_F13
00424     /* 0x17d */ { kKeyF14 },        // VK_F14
00425     /* 0x17e */ { kKeyF15 },        // VK_F15
00426     /* 0x17f */ { kKeyF16 },        // VK_F16
00427     /* 0x180 */ { kKeyF17 },        // VK_F17
00428     /* 0x181 */ { kKeyF18 },        // VK_F18
00429     /* 0x182 */ { kKeyF19 },        // VK_F19
00430     /* 0x183 */ { kKeyF20 },        // VK_F20
00431     /* 0x184 */ { kKeyF21 },        // VK_F21
00432     /* 0x185 */ { kKeyF22 },        // VK_F22
00433     /* 0x186 */ { kKeyF23 },        // VK_F23
00434     /* 0x187 */ { kKeyF24 },        // VK_F24
00435     /* 0x188 */ { kKeyNone },       // unassigned
00436     /* 0x189 */ { kKeyNone },       // unassigned
00437     /* 0x18a */ { kKeyNone },       // unassigned
00438     /* 0x18b */ { kKeyNone },       // unassigned
00439     /* 0x18c */ { kKeyNone },       // unassigned
00440     /* 0x18d */ { kKeyNone },       // unassigned
00441     /* 0x18e */ { kKeyNone },       // unassigned
00442     /* 0x18f */ { kKeyNone },       // unassigned
00443     /* 0x190 */ { kKeyNumLock },    // VK_NUMLOCK
00444     /* 0x191 */ { kKeyNone },       // VK_SCROLL
00445     /* 0x192 */ { kKeyNone },       // unassigned
00446     /* 0x193 */ { kKeyNone },       // unassigned
00447     /* 0x194 */ { kKeyNone },       // unassigned
00448     /* 0x195 */ { kKeyNone },       // unassigned
00449     /* 0x196 */ { kKeyNone },       // unassigned
00450     /* 0x197 */ { kKeyNone },       // unassigned
00451     /* 0x198 */ { kKeyNone },       // unassigned
00452     /* 0x199 */ { kKeyNone },       // unassigned
00453     /* 0x19a */ { kKeyNone },       // unassigned
00454     /* 0x19b */ { kKeyNone },       // unassigned
00455     /* 0x19c */ { kKeyNone },       // unassigned
00456     /* 0x19d */ { kKeyNone },       // unassigned
00457     /* 0x19e */ { kKeyNone },       // unassigned
00458     /* 0x19f */ { kKeyNone },       // unassigned
00459     /* 0x1a0 */ { kKeyShift_L },    // VK_LSHIFT
00460     /* 0x1a1 */ { kKeyShift_R },    // VK_RSHIFT
00461     /* 0x1a2 */ { kKeyControl_L },  // VK_LCONTROL
00462     /* 0x1a3 */ { kKeyControl_R },  // VK_RCONTROL
00463     /* 0x1a4 */ { kKeyAlt_L },      // VK_LMENU
00464     /* 0x1a5 */ { kKeyAlt_R },      // VK_RMENU
00465     /* 0x1a6 */ { kKeyWWWBack },    // VK_BROWSER_BACK
00466     /* 0x1a7 */ { kKeyWWWForward }, // VK_BROWSER_FORWARD
00467     /* 0x1a8 */ { kKeyWWWRefresh }, // VK_BROWSER_REFRESH
00468     /* 0x1a9 */ { kKeyWWWStop },    // VK_BROWSER_STOP
00469     /* 0x1aa */ { kKeyWWWSearch },  // VK_BROWSER_SEARCH
00470     /* 0x1ab */ { kKeyWWWFavorites },// VK_BROWSER_FAVORITES
00471     /* 0x1ac */ { kKeyWWWHome },    // VK_BROWSER_HOME
00472     /* 0x1ad */ { kKeyAudioMute },  // VK_VOLUME_MUTE
00473     /* 0x1ae */ { kKeyAudioDown },  // VK_VOLUME_DOWN
00474     /* 0x1af */ { kKeyAudioUp },    // VK_VOLUME_UP
00475     /* 0x1b0 */ { kKeyAudioNext },  // VK_MEDIA_NEXT_TRACK
00476     /* 0x1b1 */ { kKeyAudioPrev },  // VK_MEDIA_PREV_TRACK
00477     /* 0x1b2 */ { kKeyAudioStop },  // VK_MEDIA_STOP
00478     /* 0x1b3 */ { kKeyAudioPlay },  // VK_MEDIA_PLAY_PAUSE
00479     /* 0x1b4 */ { kKeyAppMail },    // VK_LAUNCH_MAIL
00480     /* 0x1b5 */ { kKeyAppMedia },   // VK_LAUNCH_MEDIA_SELECT
00481     /* 0x1b6 */ { kKeyAppUser1 },   // VK_LAUNCH_APP1
00482     /* 0x1b7 */ { kKeyAppUser2 },   // VK_LAUNCH_APP2
00483     /* 0x1b8 */ { kKeyNone },       // unassigned
00484     /* 0x1b9 */ { kKeyNone },       // unassigned
00485     /* 0x1ba */ { kKeyNone },       // OEM specific
00486     /* 0x1bb */ { kKeyNone },       // OEM specific
00487     /* 0x1bc */ { kKeyNone },       // OEM specific
00488     /* 0x1bd */ { kKeyNone },       // OEM specific
00489     /* 0x1be */ { kKeyNone },       // OEM specific
00490     /* 0x1bf */ { kKeyNone },       // OEM specific
00491     /* 0x1c0 */ { kKeyNone },       // OEM specific
00492     /* 0x1c1 */ { kKeyNone },       // unassigned
00493     /* 0x1c2 */ { kKeyNone },       // unassigned
00494     /* 0x1c3 */ { kKeyNone },       // unassigned
00495     /* 0x1c4 */ { kKeyNone },       // unassigned
00496     /* 0x1c5 */ { kKeyNone },       // unassigned
00497     /* 0x1c6 */ { kKeyNone },       // unassigned
00498     /* 0x1c7 */ { kKeyNone },       // unassigned
00499     /* 0x1c8 */ { kKeyNone },       // unassigned
00500     /* 0x1c9 */ { kKeyNone },       // unassigned
00501     /* 0x1ca */ { kKeyNone },       // unassigned
00502     /* 0x1cb */ { kKeyNone },       // unassigned
00503     /* 0x1cc */ { kKeyNone },       // unassigned
00504     /* 0x1cd */ { kKeyNone },       // unassigned
00505     /* 0x1ce */ { kKeyNone },       // unassigned
00506     /* 0x1cf */ { kKeyNone },       // unassigned
00507     /* 0x1d0 */ { kKeyNone },       // unassigned
00508     /* 0x1d1 */ { kKeyNone },       // unassigned
00509     /* 0x1d2 */ { kKeyNone },       // unassigned
00510     /* 0x1d3 */ { kKeyNone },       // unassigned
00511     /* 0x1d4 */ { kKeyNone },       // unassigned
00512     /* 0x1d5 */ { kKeyNone },       // unassigned
00513     /* 0x1d6 */ { kKeyNone },       // unassigned
00514     /* 0x1d7 */ { kKeyNone },       // unassigned
00515     /* 0x1d8 */ { kKeyNone },       // unassigned
00516     /* 0x1d9 */ { kKeyNone },       // unassigned
00517     /* 0x1da */ { kKeyNone },       // unassigned
00518     /* 0x1db */ { kKeyNone },       // OEM specific
00519     /* 0x1dc */ { kKeyNone },       // OEM specific
00520     /* 0x1dd */ { kKeyNone },       // OEM specific
00521     /* 0x1de */ { kKeyNone },       // OEM specific
00522     /* 0x1df */ { kKeyNone },       // OEM specific
00523     /* 0x1e0 */ { kKeyNone },       // OEM specific
00524     /* 0x1e1 */ { kKeyNone },       // OEM specific
00525     /* 0x1e2 */ { kKeyNone },       // OEM specific
00526     /* 0x1e3 */ { kKeyNone },       // OEM specific
00527     /* 0x1e4 */ { kKeyNone },       // OEM specific
00528     /* 0x1e5 */ { kKeyNone },       // unassigned
00529     /* 0x1e6 */ { kKeyNone },       // OEM specific
00530     /* 0x1e7 */ { kKeyNone },       // unassigned
00531     /* 0x1e8 */ { kKeyNone },       // unassigned
00532     /* 0x1e9 */ { kKeyNone },       // OEM specific
00533     /* 0x1ea */ { kKeyNone },       // OEM specific
00534     /* 0x1eb */ { kKeyNone },       // OEM specific
00535     /* 0x1ec */ { kKeyNone },       // OEM specific
00536     /* 0x1ed */ { kKeyNone },       // OEM specific
00537     /* 0x1ee */ { kKeyNone },       // OEM specific
00538     /* 0x1ef */ { kKeyNone },       // OEM specific
00539     /* 0x1f0 */ { kKeyNone },       // OEM specific
00540     /* 0x1f1 */ { kKeyNone },       // OEM specific
00541     /* 0x1f2 */ { kKeyNone },       // VK_OEM_COPY
00542     /* 0x1f3 */ { kKeyNone },       // VK_OEM_AUTO
00543     /* 0x1f4 */ { kKeyNone },       // VK_OEM_ENLW
00544     /* 0x1f5 */ { kKeyNone },       // OEM specific
00545     /* 0x1f6 */ { kKeyNone },       // VK_ATTN          
00546     /* 0x1f7 */ { kKeyNone },       // VK_CRSEL         
00547     /* 0x1f8 */ { kKeyNone },       // VK_EXSEL         
00548     /* 0x1f9 */ { kKeyNone },       // VK_EREOF         
00549     /* 0x1fa */ { kKeyNone },       // VK_PLAY          
00550     /* 0x1fb */ { kKeyNone },       // VK_ZOOM          
00551     /* 0x1fc */ { kKeyNone },       // reserved
00552     /* 0x1fd */ { kKeyNone },       // VK_PA1           
00553     /* 0x1fe */ { kKeyNone },       // VK_OEM_CLEAR     
00554     /* 0x1ff */ { kKeyNone }        // reserved
00555 };
00556 
00557 struct CWin32Modifiers {
00558 public:
00559     UINT                m_vk;
00560     KeyModifierMask     m_mask;
00561 };
00562 
00563 static const CWin32Modifiers s_modifiers[] =
00564 {
00565     { VK_SHIFT,    KeyModifierShift   },
00566     { VK_LSHIFT,   KeyModifierShift   },
00567     { VK_RSHIFT,   KeyModifierShift   },
00568     { VK_CONTROL,  KeyModifierControl },
00569     { VK_LCONTROL, KeyModifierControl },
00570     { VK_RCONTROL, KeyModifierControl },
00571     { VK_MENU,     KeyModifierAlt     },
00572     { VK_LMENU,    KeyModifierAlt     },
00573     { VK_RMENU,    KeyModifierAlt     },
00574     { VK_LWIN,     KeyModifierSuper   },
00575     { VK_RWIN,     KeyModifierSuper   }
00576 };
00577 
00578 CMSWindowsKeyState::CMSWindowsKeyState(
00579     CMSWindowsDesks* desks, void* eventTarget) :
00580     m_is95Family(CArchMiscWindows::isWindows95Family()),
00581     m_eventTarget(eventTarget),
00582     m_desks(desks),
00583     m_keyLayout(GetKeyboardLayout(0)),
00584     m_fixTimer(NULL),
00585     m_lastDown(0),
00586     m_useSavedModifiers(false),
00587     m_savedModifiers(0),
00588     m_originalSavedModifiers(0),
00589     m_eventQueue(*EVENTQUEUE)
00590 {
00591     init();
00592 }
00593 
00594 CMSWindowsKeyState::CMSWindowsKeyState(
00595     CMSWindowsDesks* desks, void* eventTarget, IEventQueue& eventQueue, CKeyMap& keyMap) :
00596     CKeyState(eventQueue, keyMap),
00597     m_is95Family(CArchMiscWindows::isWindows95Family()),
00598     m_eventTarget(eventTarget),
00599     m_desks(desks),
00600     m_keyLayout(GetKeyboardLayout(0)),
00601     m_fixTimer(NULL),
00602     m_lastDown(0),
00603     m_useSavedModifiers(false),
00604     m_savedModifiers(0),
00605     m_originalSavedModifiers(0),
00606     m_eventQueue(eventQueue)
00607 {
00608     init();
00609 }
00610 
00611 CMSWindowsKeyState::~CMSWindowsKeyState()
00612 {
00613     disable();
00614 }
00615 
00616 void
00617 CMSWindowsKeyState::init()
00618 {
00619     // look up symbol that's available on winNT family but not win95
00620     HMODULE userModule = GetModuleHandle("user32.dll");
00621     m_ToUnicodeEx = (ToUnicodeEx_t)GetProcAddress(userModule, "ToUnicodeEx");
00622 }
00623 
00624 void
00625 CMSWindowsKeyState::disable()
00626 {
00627     if (m_fixTimer != NULL) {
00628         getEventQueue().removeHandler(CEvent::kTimer, m_fixTimer);
00629         getEventQueue().deleteTimer(m_fixTimer);
00630         m_fixTimer = NULL;
00631     }
00632     m_lastDown = 0;
00633 }
00634 
00635 KeyButton
00636 CMSWindowsKeyState::virtualKeyToButton(UINT virtualKey) const
00637 {
00638     return m_virtualKeyToButton[virtualKey & 0xffu];
00639 }
00640 
00641 void
00642 CMSWindowsKeyState::setKeyLayout(HKL keyLayout)
00643 {
00644     m_keyLayout = keyLayout;
00645 }
00646 
00647 bool
00648 CMSWindowsKeyState::testAutoRepeat(bool press, bool isRepeat, KeyButton button)
00649 {
00650     if (!isRepeat) {
00651         isRepeat = (press && m_lastDown != 0 && button == m_lastDown);
00652     }
00653     if (press) {
00654         m_lastDown = button;
00655     }
00656     else {
00657         m_lastDown = 0;
00658     }
00659     return isRepeat;
00660 }
00661 
00662 void
00663 CMSWindowsKeyState::saveModifiers()
00664 {
00665     m_savedModifiers         = getActiveModifiers();
00666     m_originalSavedModifiers = m_savedModifiers;
00667 }
00668 
00669 void
00670 CMSWindowsKeyState::useSavedModifiers(bool enable)
00671 {
00672     if (enable != m_useSavedModifiers) {
00673         m_useSavedModifiers = enable;
00674         if (!m_useSavedModifiers) {
00675             // transfer any modifier state changes to CKeyState's state
00676             KeyModifierMask mask = m_originalSavedModifiers ^ m_savedModifiers;
00677             getActiveModifiersRValue() =
00678                 (getActiveModifiers() & ~mask) | (m_savedModifiers & mask);
00679         }
00680     }
00681 }
00682 
00683 KeyID
00684 CMSWindowsKeyState::mapKeyFromEvent(WPARAM charAndVirtKey,
00685                 LPARAM info, KeyModifierMask* maskOut) const
00686 {
00687     static const KeyModifierMask s_controlAlt =
00688         KeyModifierControl | KeyModifierAlt;
00689 
00690     // extract character, virtual key, and if we didn't use AltGr
00691     char c       = (char)((charAndVirtKey & 0xff00u) >> 8);
00692     UINT vkCode  = (charAndVirtKey & 0xffu);
00693     bool noAltGr = ((charAndVirtKey & 0xff0000u) != 0);
00694 
00695     // handle some keys via table lookup
00696     KeyID id     = getKeyID(vkCode, (KeyButton)((info >> 16) & 0x1ffu));
00697 
00698     // check if not in table;  map character to key id
00699     if (id == kKeyNone && c != 0) {
00700         if ((c & 0x80u) == 0) {
00701             // ASCII
00702             id = static_cast<KeyID>(c) & 0xffu;
00703         }
00704         else {
00705             // character is not really ASCII.  instead it's some
00706             // character in the current ANSI code page.  try to
00707             // convert that to a Unicode character.  if we fail
00708             // then use the single byte character as is.
00709             char src = c;
00710             wchar_t unicode;
00711             if (MultiByteToWideChar(CP_THREAD_ACP, MB_PRECOMPOSED,
00712                                         &src, 1, &unicode, 1) > 0) {
00713                 id = static_cast<KeyID>(unicode);
00714             }
00715             else {
00716                 id = static_cast<KeyID>(c) & 0xffu;
00717             }
00718         }
00719     }
00720 
00721     // set modifier mask
00722     if (maskOut != NULL) {
00723         KeyModifierMask active = getActiveModifiers();
00724         if (!noAltGr && (active & s_controlAlt) == s_controlAlt) {
00725             // if !noAltGr then we're only interested in matching the
00726             // key, not the AltGr.  AltGr is down (i.e. control and alt
00727             // are down) but we don't want the client to have to match
00728             // that so we clear it.
00729             active &= ~s_controlAlt;
00730         }
00731         *maskOut = active;
00732     }
00733 
00734     return id;
00735 }
00736 
00737 bool
00738 CMSWindowsKeyState::didGroupsChange() const
00739 {
00740     GroupList groups;
00741     return (getGroups(groups) && groups != m_groups);
00742 }
00743 
00744 UINT
00745 CMSWindowsKeyState::mapKeyToVirtualKey(KeyID key) const
00746 {
00747     if (key == kKeyNone) {
00748         return 0;
00749     }
00750     KeyToVKMap::const_iterator i = m_keyToVKMap.find(key);
00751     if (i == m_keyToVKMap.end()) {
00752         return 0;
00753     }
00754     else {
00755         return i->second;
00756     }
00757 }
00758 
00759 void
00760 CMSWindowsKeyState::onKey(KeyButton button, bool down, KeyModifierMask newState)
00761 {
00762     // handle win32 brokenness and forward to superclass
00763     fixKeys();
00764     CKeyState::onKey(button, down, newState);
00765     fixKeys();
00766 }
00767 
00768 void
00769 CMSWindowsKeyState::sendKeyEvent(void* target,
00770                             bool press, bool isAutoRepeat,
00771                             KeyID key, KeyModifierMask mask,
00772                             SInt32 count, KeyButton button)
00773 {
00774     if (press || isAutoRepeat) {
00775         // send key
00776         if (press && !isAutoRepeat) {
00777             CKeyState::sendKeyEvent(target, true, false,
00778                             key, mask, 1, button);
00779             if (count > 0) {
00780                 --count;
00781             }
00782         }
00783         if (count >= 1) {
00784             CKeyState::sendKeyEvent(target, true, true,
00785                             key, mask, count, button);
00786         }
00787     }
00788     else {
00789         // do key up
00790         CKeyState::sendKeyEvent(target, false, false, key, mask, 1, button);
00791     }
00792 }
00793 
00794 void
00795 CMSWindowsKeyState::fakeKeyDown(KeyID id, KeyModifierMask mask,
00796                 KeyButton button)
00797 {
00798     CKeyState::fakeKeyDown(id, mask, button);
00799 }
00800 
00801 bool
00802 CMSWindowsKeyState::fakeKeyRepeat(KeyID id, KeyModifierMask mask,
00803                 SInt32 count, KeyButton button)
00804 {
00805     return CKeyState::fakeKeyRepeat(id, mask, count, button);
00806 }
00807 
00808 bool
00809 CMSWindowsKeyState::fakeCtrlAltDel()
00810 {
00811     if (!m_is95Family) {
00812         // to fake ctrl+alt+del on the NT family we broadcast a suitable
00813         // hotkey to all windows on the winlogon desktop.  however, the
00814         // current thread must be on that desktop to do the broadcast
00815         // and we can't switch just any thread because some own windows
00816         // or hooks.  so start a new thread to do the real work.
00817         HANDLE hEvtSendSas = OpenEvent( EVENT_MODIFY_STATE, FALSE, "Global\\SendSAS" );
00818         if ( hEvtSendSas ) {
00819             LOG((CLOG_DEBUG "found the SendSAS event - signaling my launcher to simulate ctrl+alt+del"));
00820             SetEvent( hEvtSendSas );
00821             CloseHandle( hEvtSendSas );
00822         }
00823         else {
00824         CThread cad(new CFunctionJob(&CMSWindowsKeyState::ctrlAltDelThread));
00825         cad.wait();
00826     }
00827     }
00828     else {
00829         // simulate ctrl+alt+del
00830         fakeKeyDown(kKeyDelete, KeyModifierControl | KeyModifierAlt,
00831                             virtualKeyToButton(VK_DELETE));
00832     }
00833     return true;
00834 }
00835 
00836 void
00837 CMSWindowsKeyState::ctrlAltDelThread(void*)
00838 {
00839     // get the Winlogon desktop at whatever privilege we can
00840     HDESK desk = OpenDesktop("Winlogon", 0, FALSE, MAXIMUM_ALLOWED);
00841     if (desk != NULL) {
00842         if (SetThreadDesktop(desk)) {
00843             PostMessage(HWND_BROADCAST, WM_HOTKEY, 0,
00844                         MAKELPARAM(MOD_CONTROL | MOD_ALT, VK_DELETE));
00845         }
00846         else {
00847             LOG((CLOG_DEBUG "can't switch to Winlogon desk: %d", GetLastError()));
00848         }
00849         CloseDesktop(desk);
00850     }
00851     else {
00852         LOG((CLOG_DEBUG "can't open Winlogon desk: %d", GetLastError()));
00853     }
00854 }
00855 
00856 KeyModifierMask
00857 CMSWindowsKeyState::pollActiveModifiers() const
00858 {
00859     KeyModifierMask state = 0;
00860 
00861     // get non-toggle modifiers from our own shadow key state
00862     for (size_t i = 0; i < sizeof(s_modifiers) / sizeof(s_modifiers[0]); ++i) {
00863         KeyButton button = virtualKeyToButton(s_modifiers[i].m_vk);
00864         if (button != 0 && isKeyDown(button)) {
00865             state |= s_modifiers[i].m_mask;
00866         }
00867     }
00868 
00869     // we can get toggle modifiers from the system
00870     if ((GetKeyState(VK_CAPITAL) & 0x01) != 0) {
00871         state |= KeyModifierCapsLock;
00872     }
00873     if ((GetKeyState(VK_NUMLOCK) & 0x01) != 0) {
00874         state |= KeyModifierNumLock;
00875     }
00876     if ((GetKeyState(VK_SCROLL) & 0x01) != 0) {
00877         state |= KeyModifierScrollLock;
00878     }
00879 
00880     return state;
00881 }
00882 
00883 SInt32
00884 CMSWindowsKeyState::pollActiveGroup() const
00885 {
00886     // determine the thread that'll receive this event
00887     HWND  targetWindow = GetForegroundWindow();
00888     DWORD targetThread = GetWindowThreadProcessId(targetWindow, NULL);
00889 
00890     // get keyboard layout for the thread
00891     HKL hkl            = GetKeyboardLayout(targetThread);
00892 
00893     if (!hkl) {
00894         // GetKeyboardLayout failed. Maybe targetWindow is a console window.
00895         // We're getting the keyboard layout of the desktop instead.
00896         targetWindow = GetDesktopWindow();
00897         targetThread = GetWindowThreadProcessId(targetWindow, NULL);
00898         hkl          = GetKeyboardLayout(targetThread);
00899     }
00900 
00901     // get group
00902     GroupMap::const_iterator i = m_groupMap.find(hkl);
00903     if (i == m_groupMap.end()) {
00904         LOG((CLOG_DEBUG1 "can't find keyboard layout %08x", hkl));
00905         return 0;
00906     }
00907 
00908     return i->second;
00909 }
00910 
00911 void
00912 CMSWindowsKeyState::pollPressedKeys(KeyButtonSet& pressedKeys) const
00913 {
00914     BYTE keyState[256];
00915     if (!GetKeyboardState(keyState)) {
00916         LOG((CLOG_ERR "GetKeyboardState returned false on pollPressedKeys"));
00917         return;
00918     }
00919     for (KeyButton i = 1; i < 256; ++i) {
00920         if ((keyState[i] & 0x80) != 0) {
00921             pressedKeys.insert(i);
00922         }
00923     }
00924 }
00925 
00926 void
00927 CMSWindowsKeyState::getKeyMap(CKeyMap& keyMap)
00928 {
00929     // update keyboard groups
00930     if (getGroups(m_groups)) {
00931         m_groupMap.clear();
00932         SInt32 numGroups = (SInt32)m_groups.size();
00933         for (SInt32 g = 0; g < numGroups; ++g) {
00934             m_groupMap[m_groups[g]] = g;
00935         }
00936     }
00937     HKL activeLayout = GetKeyboardLayout(0);
00938 
00939     // clear table
00940     memset(m_virtualKeyToButton, 0, sizeof(m_virtualKeyToButton));
00941     m_keyToVKMap.clear();
00942 
00943     CKeyMap::KeyItem item;
00944     SInt32 numGroups = (SInt32)m_groups.size();
00945     for (SInt32 g = 0; g < numGroups; ++g) {
00946         item.m_group = g;
00947         ActivateKeyboardLayout(m_groups[g], 0);
00948 
00949         // clear tables
00950         memset(m_buttonToVK, 0, sizeof(m_buttonToVK));
00951         memset(m_buttonToNumpadVK, 0, sizeof(m_buttonToNumpadVK));
00952 
00953         // map buttons (scancodes) to virtual keys
00954         for (KeyButton i = 1; i < 256; ++i) {
00955             UINT vk = MapVirtualKey(i, 1);
00956             if (vk == 0) {
00957                 // unmapped
00958                 continue;
00959             }
00960 
00961             // deal with certain virtual keys specially
00962             switch (vk) {
00963             case VK_SHIFT:
00964                 // this is important for sending the correct modifier to the 
00965                 // client, a patch from bug #242 (right shift broken for ms
00966                 // remote desktop) removed this to just use left shift, which
00967                 // caused bug #2799 (right shift broken for osx).
00968                 // we must not repeat this same mistake and must fix platform
00969                 // specific bugs in code that only affects that platform.
00970                 if (MapVirtualKey(VK_RSHIFT, 0) == i) {
00971                     vk = VK_RSHIFT;
00972                 }
00973                 else {
00974                     vk = VK_LSHIFT;
00975                 }
00976                 break;
00977 
00978             case VK_CONTROL:
00979                 vk = VK_LCONTROL;
00980                 break;
00981 
00982             case VK_MENU:
00983                 vk = VK_LMENU;
00984                 break;
00985 
00986             case VK_NUMLOCK:
00987                 vk = VK_PAUSE;
00988                 break;
00989 
00990             case VK_NUMPAD0:
00991             case VK_NUMPAD1:
00992             case VK_NUMPAD2:
00993             case VK_NUMPAD3:
00994             case VK_NUMPAD4:
00995             case VK_NUMPAD5:
00996             case VK_NUMPAD6:
00997             case VK_NUMPAD7:
00998             case VK_NUMPAD8:
00999             case VK_NUMPAD9:
01000             case VK_DECIMAL:
01001                 // numpad keys are saved in their own table
01002                 m_buttonToNumpadVK[i] = vk;
01003                 continue;
01004 
01005             case VK_LWIN:
01006             case VK_RWIN:
01007                 // add extended key only for these on 95 family
01008                 if (m_is95Family) {
01009                     m_buttonToVK[i | 0x100u] = vk;
01010                     continue;
01011                 }
01012                 break;
01013 
01014             case VK_RETURN:
01015             case VK_PRIOR:
01016             case VK_NEXT:
01017             case VK_END:
01018             case VK_HOME:
01019             case VK_LEFT:
01020             case VK_UP:
01021             case VK_RIGHT:
01022             case VK_DOWN:
01023             case VK_INSERT:
01024             case VK_DELETE:
01025                 // also add extended key for these
01026                 m_buttonToVK[i | 0x100u] = vk;
01027                 break;
01028             }
01029 
01030             if (m_buttonToVK[i] == 0) {
01031                 m_buttonToVK[i] = vk;
01032             }
01033         }
01034 
01035         // now map virtual keys to buttons.  multiple virtual keys may map
01036         // to a single button.  if the virtual key matches the one in
01037         // m_buttonToVK then we use the button as is.  if not then it's
01038         // either a numpad key and we use the button as is or it's an
01039         // extended button.
01040         for (UINT i = 1; i < 255; ++i) {
01041             // skip virtual keys we don't want
01042             switch (i) {
01043             case VK_LBUTTON:
01044             case VK_RBUTTON:
01045             case VK_MBUTTON:
01046             case VK_XBUTTON1:
01047             case VK_XBUTTON2:
01048             case VK_SHIFT:
01049             case VK_CONTROL:
01050             case VK_MENU:
01051                 continue;
01052             }
01053 
01054             // get the button
01055             KeyButton button = static_cast<KeyButton>(MapVirtualKey(i, 0));
01056             if (button == 0) {
01057                 continue;
01058             }
01059 
01060             // deal with certain virtual keys specially
01061             switch (i) {
01062             case VK_NUMPAD0:
01063             case VK_NUMPAD1:
01064             case VK_NUMPAD2:
01065             case VK_NUMPAD3:
01066             case VK_NUMPAD4:
01067             case VK_NUMPAD5:
01068             case VK_NUMPAD6:
01069             case VK_NUMPAD7:
01070             case VK_NUMPAD8:
01071             case VK_NUMPAD9:
01072             case VK_DECIMAL:
01073                 m_buttonToNumpadVK[button] = i;
01074                 break;
01075 
01076             default:
01077                 // add extended key if virtual keys don't match
01078                 if (m_buttonToVK[button] != i) {
01079                     m_buttonToVK[button | 0x100u] = i;
01080                 }
01081                 break;
01082             }
01083         }
01084 
01085         // add alt+printscreen
01086         if (m_buttonToVK[0x54u] == 0) {
01087             m_buttonToVK[0x54u] = VK_SNAPSHOT;
01088         }
01089 
01090         // set virtual key to button table
01091         if (GetKeyboardLayout(0) == m_groups[g]) {
01092             for (KeyButton i = 0; i < 512; ++i) {
01093                 if (m_buttonToVK[i] != 0) {
01094                     if (m_virtualKeyToButton[m_buttonToVK[i]] == 0) {
01095                         m_virtualKeyToButton[m_buttonToVK[i]] = i;
01096                     }
01097                 }
01098                 if (m_buttonToNumpadVK[i] != 0) {
01099                     if (m_virtualKeyToButton[m_buttonToNumpadVK[i]] == 0) {
01100                         m_virtualKeyToButton[m_buttonToNumpadVK[i]] = i;
01101                     }
01102                 }
01103             }
01104         }
01105 
01106         // add numpad keys
01107         for (KeyButton i = 0; i < 512; ++i) {
01108             if (m_buttonToNumpadVK[i] != 0) {
01109                 item.m_id        = getKeyID(m_buttonToNumpadVK[i], i);
01110                 item.m_button    = i;
01111                 item.m_required  = KeyModifierNumLock;
01112                 item.m_sensitive = KeyModifierNumLock | KeyModifierShift;
01113                 item.m_generates = 0;
01114                 item.m_client    = m_buttonToNumpadVK[i];
01115                 addKeyEntry(keyMap, item);
01116             }
01117         }
01118 
01119         // add other keys
01120         BYTE keys[256];
01121         memset(keys, 0, sizeof(keys));
01122         for (KeyButton i = 0; i < 512; ++i) {
01123             if (m_buttonToVK[i] != 0) {
01124                 // initialize item
01125                 item.m_id        = getKeyID(m_buttonToVK[i], i);
01126                 item.m_button    = i;
01127                 item.m_required  = 0;
01128                 item.m_sensitive = 0;
01129                 item.m_client    = m_buttonToVK[i];
01130 
01131                 // get flags for modifier keys
01132                 CKeyMap::initModifierKey(item);
01133 
01134                 if (item.m_id == 0) {
01135                     // translate virtual key to a character with and without
01136                     // shift, caps lock, and AltGr.
01137                     struct Modifier {
01138                         UINT            m_vk1;
01139                         UINT            m_vk2;
01140                         BYTE            m_state;
01141                         KeyModifierMask m_mask;
01142                     };
01143                     static const Modifier modifiers[] = {
01144                         { VK_SHIFT,   VK_SHIFT,   0x80u, KeyModifierShift    },
01145                         { VK_CAPITAL, VK_CAPITAL, 0x01u, KeyModifierCapsLock },
01146                         { VK_CONTROL, VK_MENU,    0x80u, KeyModifierControl |
01147                                                          KeyModifierAlt      }
01148                     };
01149                     static const size_t s_numModifiers =
01150                         sizeof(modifiers) / sizeof(modifiers[0]);
01151                     static const size_t s_numCombinations = 1 << s_numModifiers;
01152                     KeyID id[s_numCombinations];
01153 
01154                     bool anyFound = false;
01155                     KeyButton button = static_cast<KeyButton>(i & 0xffu);
01156                     for (size_t j = 0; j < s_numCombinations; ++j) {
01157                         for (size_t k = 0; k < s_numModifiers; ++k) {
01158                             //if ((j & (1 << k)) != 0) {
01159                             // http://msdn.microsoft.com/en-us/library/ke55d167.aspx
01160                             if ((j & (1i64 << k)) != 0) {
01161                                 keys[modifiers[k].m_vk1] = modifiers[k].m_state;
01162                                 keys[modifiers[k].m_vk2] = modifiers[k].m_state;
01163                             }
01164                             else {
01165                                 keys[modifiers[k].m_vk1] = 0;
01166                                 keys[modifiers[k].m_vk2] = 0;
01167                             }
01168                         }
01169                         id[j] = getIDForKey(item, button,
01170                                         m_buttonToVK[i], keys, m_groups[g]);
01171                         if (id[j] != 0) {
01172                             anyFound = true;
01173                         }
01174                     }
01175 
01176                     if (anyFound) {
01177                         // determine what modifiers we're sensitive to.
01178                         // we're sensitive if the KeyID changes when the
01179                         // modifier does.
01180                         item.m_sensitive = 0;
01181                         for (size_t k = 0; k < s_numModifiers; ++k) {
01182                             for (size_t j = 0; j < s_numCombinations; ++j) {
01183                                 //if (id[j] != id[j ^ (1u << k)]) {
01184                                 // http://msdn.microsoft.com/en-us/library/ke55d167.aspx
01185                                 if (id[j] != id[j ^ (1ui64 << k)]) {
01186                                     item.m_sensitive |= modifiers[k].m_mask;
01187                                     break;
01188                                 }
01189                             }
01190                         }
01191                         
01192                         // save each key.  the map will automatically discard
01193                         // duplicates, like an unshift and shifted version of
01194                         // a key that's insensitive to shift.
01195                         for (size_t j = 0; j < s_numCombinations; ++j) {
01196                             item.m_id       = id[j];
01197                             item.m_required = 0;
01198                             for (size_t k = 0; k < s_numModifiers; ++k) {
01199                                 if ((j & (1i64 << k)) != 0) {
01200                                     item.m_required |= modifiers[k].m_mask;
01201                                 }
01202                             }
01203                             addKeyEntry(keyMap, item);
01204                         }
01205                     }
01206                 }
01207                 else {
01208                     // found in table
01209                     switch (m_buttonToVK[i]) {
01210                     case VK_TAB:
01211                         // add kKeyLeftTab, too
01212                         item.m_id         = kKeyLeftTab;
01213                         item.m_required  |= KeyModifierShift;
01214                         item.m_sensitive |= KeyModifierShift;
01215                         addKeyEntry(keyMap, item);
01216                         item.m_id         = kKeyTab;
01217                         item.m_required  &= ~KeyModifierShift;
01218                         break;
01219 
01220                     case VK_CANCEL:
01221                         item.m_required  |= KeyModifierControl;
01222                         item.m_sensitive |= KeyModifierControl;
01223                         break;
01224 
01225                     case VK_SNAPSHOT:
01226                         item.m_sensitive |= KeyModifierAlt;
01227                         if ((i & 0x100u) == 0) {
01228                             // non-extended snapshot key requires alt
01229                             item.m_required |= KeyModifierAlt;
01230                         }
01231                         break;
01232                     }
01233                     addKeyEntry(keyMap, item);
01234                 }
01235             }
01236         }
01237     }
01238 
01239     // restore keyboard layout
01240     ActivateKeyboardLayout(activeLayout, 0);
01241 }
01242 
01243 void
01244 CMSWindowsKeyState::fakeKey(const Keystroke& keystroke)
01245 {
01246     switch (keystroke.m_type) {
01247     case Keystroke::kButton: {
01248         LOG((CLOG_DEBUG1 "  %03x (%08x) %s", keystroke.m_data.m_button.m_button, keystroke.m_data.m_button.m_client, keystroke.m_data.m_button.m_press ? "down" : "up"));
01249         KeyButton button = keystroke.m_data.m_button.m_button;
01250 
01251         // windows doesn't send key ups for key repeats
01252         if (keystroke.m_data.m_button.m_repeat &&
01253             !keystroke.m_data.m_button.m_press) {
01254             LOG((CLOG_DEBUG1 "  discard key repeat release"));
01255             break;
01256         }
01257 
01258         // get the virtual key for the button
01259         UINT vk = keystroke.m_data.m_button.m_client;
01260 
01261         // special handling of VK_SNAPSHOT
01262         if (vk == VK_SNAPSHOT) {
01263             if ((getActiveModifiers() & KeyModifierAlt) != 0) {
01264                 // snapshot active window
01265                 button = 1;
01266             }
01267             else {
01268                 // snapshot full screen
01269                 button = 0;
01270             }
01271         }
01272 
01273         // synthesize event
01274         m_desks->fakeKeyEvent(button, vk,
01275                                 keystroke.m_data.m_button.m_press,
01276                                 keystroke.m_data.m_button.m_repeat);
01277         break;
01278     }
01279 
01280     case Keystroke::kGroup:
01281         // we don't restore the group.  we'd like to but we can't be
01282         // sure the restoring group change will be processed after the
01283         // key events.
01284         if (!keystroke.m_data.m_group.m_restore) {
01285             if (keystroke.m_data.m_group.m_absolute) {
01286                 LOG((CLOG_DEBUG1 "  group %d", keystroke.m_data.m_group.m_group));
01287                 setWindowGroup(keystroke.m_data.m_group.m_group);
01288             }
01289             else {
01290                 LOG((CLOG_DEBUG1 "  group %+d", keystroke.m_data.m_group.m_group));
01291                 setWindowGroup(getEffectiveGroup(pollActiveGroup(),
01292                                     keystroke.m_data.m_group.m_group));
01293             }
01294         }
01295         break;
01296     }
01297 }
01298 
01299 KeyModifierMask&
01300 CMSWindowsKeyState::getActiveModifiersRValue()
01301 {
01302     if (m_useSavedModifiers) {
01303         return m_savedModifiers;
01304     }
01305     else {
01306         return CKeyState::getActiveModifiersRValue();
01307     }
01308 }
01309 
01310 bool
01311 CMSWindowsKeyState::getGroups(GroupList& groups) const
01312 {
01313     // get keyboard layouts
01314     UInt32 newNumLayouts = GetKeyboardLayoutList(0, NULL);
01315     if (newNumLayouts == 0) {
01316         LOG((CLOG_DEBUG1 "can't get keyboard layouts"));
01317         return false;
01318     }
01319     HKL* newLayouts = new HKL[newNumLayouts];
01320     newNumLayouts = GetKeyboardLayoutList(newNumLayouts, newLayouts);
01321     if (newNumLayouts == 0) {
01322         LOG((CLOG_DEBUG1 "can't get keyboard layouts"));
01323         delete[] newLayouts;
01324         return false;
01325     }
01326 
01327     groups.clear();
01328     groups.insert(groups.end(), newLayouts, newLayouts + newNumLayouts);
01329     delete[] newLayouts;
01330     return true;
01331 }
01332 
01333 void
01334 CMSWindowsKeyState::setWindowGroup(SInt32 group)
01335 {
01336     HWND targetWindow = GetForegroundWindow();
01337 
01338     bool sysCharSet = true;
01339     // XXX -- determine if m_groups[group] can be used with the system
01340     // character set.
01341 
01342     PostMessage(targetWindow, WM_INPUTLANGCHANGEREQUEST,
01343                                 sysCharSet ? 1 : 0, (LPARAM)m_groups[group]);
01344 
01345     // XXX -- use a short delay to let the target window process the message
01346     // before it sees the keyboard events.  i'm not sure why this is
01347     // necessary since the messages should arrive in order.  if we don't
01348     // delay, though, some of our keyboard events may disappear.
01349     Sleep(100);
01350 }
01351 
01352 void
01353 CMSWindowsKeyState::fixKeys()
01354 {
01355     // fake key releases for the windows keys if we think they're
01356     // down but they're really up.  we have to do this because if the
01357     // user presses and releases a windows key without pressing any
01358     // other key while it's down then the system will eat the key
01359     // release.  if we don't detect that and synthesize the release
01360     // then the client won't take the usual windows key release action
01361     // (which on windows is to show the start menu).
01362     //
01363     // only check on the windows 95 family since the NT family reports
01364     // the key releases as usual.
01365     if (!m_is95Family) {
01366         return;
01367     }
01368 
01369     KeyButton leftButton  = virtualKeyToButton(VK_LWIN);
01370     KeyButton rightButton = virtualKeyToButton(VK_RWIN);
01371     bool leftDown         = isKeyDown(leftButton);
01372     bool rightDown        = isKeyDown(rightButton);
01373     bool fix              = (leftDown || rightDown);
01374     if (fix) {
01375         // check if either button is not really down
01376         bool leftAsyncDown  = ((GetAsyncKeyState(VK_LWIN) & 0x8000) != 0);
01377         bool rightAsyncDown = ((GetAsyncKeyState(VK_RWIN) & 0x8000) != 0);
01378 
01379         if (leftAsyncDown != leftDown || rightAsyncDown != rightDown) {
01380             KeyModifierMask state = getActiveModifiers();
01381             if (!leftAsyncDown && !rightAsyncDown) {
01382                 // no win keys are down so remove super modifier
01383                 state &= ~KeyModifierSuper;
01384             }
01385 
01386             // report up events
01387             if (leftDown  && !leftAsyncDown) {
01388                 LOG((CLOG_DEBUG1 "event: fake key release left windows key (0x%03x)", leftButton));
01389                 CKeyState::onKey(leftButton, false, state);
01390                 CKeyState::sendKeyEvent(m_eventTarget, false, false,
01391                                 kKeySuper_L, state, 1, leftButton);
01392             }
01393             if (rightDown && !rightAsyncDown) {
01394                 LOG((CLOG_DEBUG1 "event: fake key release right windows key (0x%03x)", rightButton));
01395                 CKeyState::onKey(rightButton, false, state);
01396                 CKeyState::sendKeyEvent(m_eventTarget, false, false,
01397                                 kKeySuper_R, state, 1, rightButton);
01398             }
01399         }
01400     }
01401 
01402     if (fix && m_fixTimer == NULL) {
01403         // schedule check
01404         m_fixTimer = EVENTQUEUE->newTimer(0.1, NULL);
01405         EVENTQUEUE->adoptHandler(CEvent::kTimer, m_fixTimer,
01406                             new TMethodEventJob<CMSWindowsKeyState>(
01407                                 this, &CMSWindowsKeyState::handleFixKeys));
01408     }
01409     else if (!fix && m_fixTimer != NULL) {
01410         // remove scheduled check
01411         EVENTQUEUE->removeHandler(CEvent::kTimer, m_fixTimer);
01412         EVENTQUEUE->deleteTimer(m_fixTimer);
01413         m_fixTimer = NULL;
01414     }
01415 }
01416 
01417 void
01418 CMSWindowsKeyState::handleFixKeys(const CEvent&, void*)
01419 {
01420     fixKeys();
01421 }
01422 
01423 KeyID
01424 CMSWindowsKeyState::getKeyID(UINT virtualKey, KeyButton button)
01425 {
01426     if ((button & 0x100u) != 0) {
01427         virtualKey += 0x100u;
01428     }
01429     return s_virtualKey[virtualKey];
01430 }
01431 
01432 KeyID
01433 CMSWindowsKeyState::getIDForKey(CKeyMap::KeyItem& item,
01434                 KeyButton button, UINT virtualKey,
01435                 PBYTE keyState, HKL hkl) const
01436 {
01437     int n;
01438     KeyID id;
01439     if (m_is95Family) {
01440         // XXX -- how do we get characters not in Latin-1?
01441         WORD ascii;
01442         n  = ToAsciiEx(virtualKey, button, keyState, &ascii, 0, hkl);
01443         id = static_cast<KeyID>(ascii & 0xffu);
01444     }
01445     else {
01446         WCHAR unicode[2];
01447         n  = m_ToUnicodeEx(virtualKey, button, keyState,
01448                                 unicode, sizeof(unicode) / sizeof(unicode[0]),
01449                                 0, hkl);
01450         id = static_cast<KeyID>(unicode[0]);
01451     }
01452     switch (n) {
01453     case -1:
01454         return CKeyMap::getDeadKey(id);
01455 
01456     default:
01457     case 0:
01458         // unmapped
01459         return kKeyNone;
01460 
01461     case 1:
01462         return id;
01463 
01464     case 2:
01465         // left over dead key in buffer. this used to recurse,
01466         // but apparently this causes a stack overflow, so just
01467         // return no key instead.
01468         return kKeyNone;
01469     }
01470 }
01471 
01472 void
01473 CMSWindowsKeyState::addKeyEntry(CKeyMap& keyMap, CKeyMap::KeyItem& item)
01474 {
01475     keyMap.addKeyEntry(item);
01476     if (item.m_group == 0) {
01477         m_keyToVKMap[item.m_id] = static_cast<UINT>(item.m_client);
01478     }
01479 }

Generated on Wed May 22 2013 00:00:05 for Synergy by  doxygen 1.7.1