mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-05 08:25:32 +00:00
Fixes #2147. This potentially addresses the issues reported in #2147 where Keyman would crash due to a race condition as a critical section was not deleted before attempting to recreate it. Some logging has been added for debugging these issues. Also fixes memory leaks and another race on startup relating to loading the taskbar icon. There are still some known memory leaks because DLL_THREAD_DETACH is not called for all threads before keyman32.dll is unloaded, so those threads don't get the opportunity to clean themsselves up. However, the key danger with the csGlobals critical section has been addressed.
143 lines
4.1 KiB
C++
143 lines
4.1 KiB
C++
/*
|
|
Name: hotkeys
|
|
Copyright: Copyright (C) SIL International.
|
|
Documentation:
|
|
Description:
|
|
Create Date: 1 Aug 2006
|
|
|
|
Modified Date: 25 Oct 2016
|
|
Authors: mcdurdin
|
|
Related Files:
|
|
Dependencies:
|
|
|
|
Bugs:
|
|
Todo:
|
|
Notes:
|
|
History: 01 Aug 2006 - mcdurdin - Initial version
|
|
11 Dec 2009 - mcdurdin - I934 - x64 - Initial version
|
|
12 Mar 2010 - mcdurdin - I934 - x64 - Complete
|
|
03 Aug 2014 - mcdurdin - I4326 - V9.0 - Switch-off hotkey not working, then keyboard hotkey stopped working (win 8.1 jeremy) [High]
|
|
28 Aug 2014 - mcdurdin - I4390 - V9.0 - Free vs Pro
|
|
13 Oct 2014 - mcdurdin - I4451 - V9.0 - Language hotkeys are not working
|
|
14 Nov 2014 - mcdurdin - I4516 - V9.0 - Language hotkeys associated with non-primary keyboards do not trigger language change
|
|
27 Mar 2015 - mcdurdin - I4641 - V9.0 - Keyman can crash silently on exit due to null hotkeys being addressed
|
|
25 Oct 2016 - mcdurdin - I5136 - Remove additional product references from Keyman Engine
|
|
*/
|
|
// I5136
|
|
#include "pch.h"
|
|
|
|
#ifdef _WIN64
|
|
#error hotkeys.cpp is not required for win64.
|
|
#endif
|
|
|
|
Hotkeys *g_Hotkeys = NULL; // I4326
|
|
|
|
Hotkeys *Hotkeys::Instance() { // I4326
|
|
if(GetCurrentThreadId() != Globals::get_InitialisingThread()) {
|
|
return NULL; // Will bork on other threads given current usage :)
|
|
}
|
|
|
|
if(g_Hotkeys == NULL) {
|
|
g_Hotkeys = new Hotkeys;
|
|
g_Hotkeys->Load(); // I4390
|
|
}
|
|
|
|
return g_Hotkeys;
|
|
}
|
|
|
|
void Hotkeys::Unload() {
|
|
if (GetCurrentThreadId() != Globals::get_InitialisingThread()) {
|
|
OutputThreadDebugString("Unexpected: no other thread should be attempting to unload hotkeys");
|
|
return;
|
|
}
|
|
|
|
if (g_Hotkeys != NULL) {
|
|
delete g_Hotkeys;
|
|
g_Hotkeys = NULL;
|
|
}
|
|
}
|
|
|
|
void Hotkeys::Reload() { // I4326 // I4390
|
|
Hotkeys *hotkeys = Hotkeys::Instance(); // I4641
|
|
if(hotkeys == NULL) {
|
|
return;
|
|
}
|
|
|
|
hotkeys->Load(); // I4390
|
|
}
|
|
|
|
void Hotkeys::Load() { // I4390
|
|
SendDebugMessageFormat(0, sdmGlobal, 0, "Hotkeys::Load() enter");
|
|
m_nHotkeys = 0;
|
|
RegistryReadOnly reg(HKEY_CURRENT_USER);
|
|
|
|
/* Load interface hotkeys */
|
|
|
|
if(reg.OpenKeyReadOnly(REGSZ_KeymanHotkeys)) {
|
|
int n = 0;
|
|
char name[128];
|
|
while(reg.GetValueNames(name, 128, n++)) {
|
|
m_hotkeys[m_nHotkeys].HotkeyType = hktInterface;
|
|
m_hotkeys[m_nHotkeys].HotkeyValue = reg.ReadInteger(name);
|
|
m_hotkeys[m_nHotkeys].Target = atoi(name);
|
|
|
|
SendDebugMessageFormat(0, sdmGlobal, 0, "InterfaceHotkey[%d] = {HotkeyValue: %x, Target: %d}",
|
|
m_nHotkeys,
|
|
m_hotkeys[m_nHotkeys].HotkeyValue,
|
|
m_hotkeys[m_nHotkeys].Target);
|
|
|
|
if(++m_nHotkeys >= MAX_HOTKEYS) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
reg.CloseKey();
|
|
|
|
if(m_nHotkeys >= MAX_HOTKEYS) {
|
|
return;
|
|
}
|
|
|
|
/* Load language hotkeys */ // I4451
|
|
|
|
if(reg.OpenKeyReadOnly(REGSZ_KeymanLanguageHotkeys)) {
|
|
int nkey = 0;
|
|
WCHAR valuename[128];
|
|
while(reg.GetValueNames(valuename, 128, nkey++))
|
|
{
|
|
m_hotkeys[m_nHotkeys].HotkeyType = hktLanguage;
|
|
m_hotkeys[m_nHotkeys].hkl = (HKL) wcstoul(valuename, NULL, 16); // I4516
|
|
if(m_hotkeys[m_nHotkeys].hkl == 0) {
|
|
// Will be a guid
|
|
if(!SUCCEEDED(CLSIDFromString(valuename, &m_hotkeys[m_nHotkeys].profileGUID))) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
WCHAR hkval[64];
|
|
reg.ReadString(valuename, hkval, 64);
|
|
m_hotkeys[m_nHotkeys].HotkeyValue = _wtoi(hkval);
|
|
|
|
SendDebugMessageFormat(0, sdmGlobal, 0, "LanguageHotkey[%d] = {HotkeyValue: %x, hkl: %x, profileGUID: %ws}", m_nHotkeys,
|
|
m_hotkeys[m_nHotkeys].HotkeyValue,
|
|
m_hotkeys[m_nHotkeys].hkl,
|
|
m_hotkeys[m_nHotkeys].hkl == 0 ? valuename : L"");
|
|
|
|
if(++m_nHotkeys >= MAX_HOTKEYS) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
reg.CloseKey();
|
|
|
|
SendDebugMessageFormat(0, sdmGlobal, 0, "Hotkeys::Load() exit");
|
|
}
|
|
|
|
Hotkey *Hotkeys::GetHotkey(DWORD hotkey)
|
|
{
|
|
for(int i = 0; i < m_nHotkeys; i++)
|
|
if(m_hotkeys[i].HotkeyValue == hotkey)
|
|
return &m_hotkeys[i];
|
|
return NULL;
|
|
}
|