spice: on_activate_screen generates on_key_down for any modifier pressed

-call SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc...) only once, in RedWindow::init()
-add Application::cleanup_globals() & RedWindow::cleanup()
-cleanup LowLevelKeyboardProc()
This commit is contained in:
Arnon Gilboa 2009-12-30 12:19:54 +02:00 committed by Yaniv Kamay
parent c57bcf6f44
commit 02a07b2c06
5 changed files with 65 additions and 47 deletions

View File

@ -1062,6 +1062,32 @@ void Application::reset_sticky()
_sticky_info.key = REDKEY_INVALID;
}
struct ModifierKey {
int modifier;
RedKey key;
};
ModifierKey modifier_keys[] = {
{Platform::L_SHIFT_MODIFIER, REDKEY_L_SHIFT},
{Platform::R_SHIFT_MODIFIER, REDKEY_R_SHIFT},
{Platform::L_CTRL_MODIFIER, REDKEY_L_CTRL},
{Platform::R_CTRL_MODIFIER, REDKEY_R_CTRL},
{Platform::L_ALT_MODIFIER, REDKEY_L_ALT},
{Platform::R_ALT_MODIFIER, REDKEY_R_ALT},
};
void Application::sync_keyboard_modifiers()
{
uint32_t modifiers = Platform::get_keyboard_modifiers();
for (int i = 0; i < sizeof(modifier_keys) / sizeof(modifier_keys[0]); i++) {
if (modifiers & modifier_keys[i].modifier) {
on_key_down(modifier_keys[i].key);
} else {
on_key_up(modifier_keys[i].key);
}
}
}
void Application::on_key_down(RedKey key)
{
if (key <= 0 || key >= REDKEY_NUM_KEYS) {
@ -1179,6 +1205,7 @@ void Application::on_activate_screen(RedScreen* screen)
{
ASSERT(!_active_screen || (_active_screen == screen));
_active_screen = screen;
sync_keyboard_modifiers();
}
void Application::on_start_screen_key_interception(RedScreen* screen)
@ -1380,6 +1407,7 @@ void Application::exit_full_screen()
return;
}
LOG_INFO("");
_changing_screens = true;
release_capture();
for (int i = 0; i < (int)_screens.size(); i++) {
if (_screens[i]) {
@ -1396,27 +1424,16 @@ void Application::exit_full_screen()
restore_screens_size();
show();
_main_screen->activate();
_changing_screens = false;
}
bool Application::toggle_full_screen()
{
RedKey shift_pressed = REDKEY_INVALID;
if (_keyboard_state[REDKEY_L_SHIFT]) {
shift_pressed = REDKEY_L_SHIFT;
} else if (_keyboard_state[REDKEY_R_SHIFT]) {
shift_pressed = REDKEY_R_SHIFT;
}
if (_full_screen) {
exit_full_screen();
} else {
enter_full_screen();
}
uint32_t modifiers = Platform::get_keyboard_modifiers();
if ((shift_pressed == REDKEY_L_SHIFT && (modifiers & Platform::L_SHIFT_MODIFIER)) ||
(shift_pressed == REDKEY_R_SHIFT && (modifiers & Platform::R_SHIFT_MODIFIER))) {
on_key_down(shift_pressed);
}
return _full_screen;
}
@ -1978,15 +1995,25 @@ void Application::init_globals()
RedWindow::init();
}
void Application::cleanup_globals()
{
RedWindow::cleanup();
}
int Application::main(int argc, char** argv, const char* version_str)
{
int ret;
init_globals();
LOG_INFO("starting %s", version_str);
std::auto_ptr<Application> app(new Application());
AutoAbort auto_abort(*app.get());
if (!app->process_cmd_line(argc, argv)) {
return app->_exit_code;
if (app->process_cmd_line(argc, argv)) {
ret = app->run();
} else {
ret = app->_exit_code;
}
return app->run();
cleanup_globals();
return ret;
}

View File

@ -265,9 +265,11 @@ private:
bool unpress_key(RedKey key);
void reset_sticky();
static bool is_sticky_trace_key(RedKey key);
void sync_keyboard_modifiers();
static void init_logger();
static void init_globals();
static void cleanup_globals();
friend class DisconnectedEvent;
friend class ConnectionErrorEvent;

View File

@ -86,6 +86,7 @@ public:
void unset_type_gl();
static void init();
static void cleanup();
Listener& get_listener() { return _listener;}

View File

@ -35,6 +35,7 @@ static ATOM class_atom = 0;
static const LPCWSTR win_class_name = L"redc_wclass";
static HWND focus_window = NULL;
static HHOOK low_keyboard_hook = NULL;
static bool low_keyboard_hook_on = false;
static HHOOK msg_filter_hook = NULL;
typedef std::list<RedKey> KeysList;
static KeysList filtered_up_keys;
@ -714,30 +715,14 @@ Point RedWindow::get_size()
static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if ((nCode == HC_ACTION)) {
if (low_keyboard_hook_on && focus_window && nCode == HC_ACTION) {
KBDLLHOOKSTRUCT *hooked = (KBDLLHOOKSTRUCT*)lParam;
DWORD dwMsg = 1;
DWORD dwMsg = (hooked->flags << 24) | (hooked->scanCode << 16) | 1;
// dwMsg shall contain the information that would be stored
// in the usual lParam argument of a WM_KEYDOWN message.
// All information like hardware scan code and other flags
// are stored within one double word at different bit offsets.
// Refer to MSDN for further information:
//
// (Keystroke Messages)
dwMsg += hooked->scanCode << 16;
dwMsg += hooked->flags << 24;
// In some cases scan code of VK_RSHIFT is fake shift (probably a bug) so we
// convert it to non extended code. Also, QEmu doesn't expect num-lock to be
// an extended key.
if ((hooked->vkCode == VK_NUMLOCK) || (hooked->vkCode == VK_RSHIFT)) {
if (hooked->vkCode == VK_NUMLOCK || hooked->vkCode == VK_RSHIFT) {
dwMsg &= ~(1 << 24);
SendMessage(focus_window, wParam, hooked->vkCode, dwMsg);
}
SendMessage(focus_window, wParam, hooked->vkCode, dwMsg);
// Forward all modifier key strokes to update keyboard leds & shift/ctrl/alt state
switch (hooked->vkCode) {
case VK_CAPITAL:
case VK_SCROLL:
@ -750,34 +735,25 @@ static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lP
case VK_RMENU:
break;
default:
SendMessage(focus_window, wParam, hooked->vkCode, dwMsg);
return 1;
}
}
// In all other cases, we call the next hook and return it's value.
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
void RedWindow::do_start_key_interception()
{
low_keyboard_hook_on = true;
_key_interception_on = true;
_listener.on_start_key_interception();
if (low_keyboard_hook) {
return;
}
low_keyboard_hook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc,
GetModuleHandle(NULL), 0);
}
void RedWindow::do_stop_key_interception()
{
low_keyboard_hook_on = false;
_key_interception_on = false;
_listener.on_stop_key_interception();
if (!low_keyboard_hook) {
return;
}
UnhookWindowsHookEx(low_keyboard_hook);
low_keyboard_hook = NULL;
}
void RedWindow::start_key_interception()
@ -807,6 +783,13 @@ void RedWindow::init()
if (!(class_atom = register_class(instance))) {
THROW("register class failed");
}
low_keyboard_hook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc,
GetModuleHandle(NULL), 0);
}
void RedWindow::cleanup()
{
UnhookWindowsHookEx(low_keyboard_hook);
}
#ifdef USE_OGL
@ -850,6 +833,7 @@ void RedWindow::on_focus_out()
}
_focused = false;
focus_window = NULL;
if (_key_interception_on) {
do_stop_key_interception();

View File

@ -2046,3 +2046,7 @@ void RedWindow::init()
#endif
}
void RedWindow::cleanup()
{
}