mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2025-12-27 23:49:04 +00:00
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:
parent
c57bcf6f44
commit
02a07b2c06
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -86,6 +86,7 @@ public:
|
||||
void unset_type_gl();
|
||||
|
||||
static void init();
|
||||
static void cleanup();
|
||||
|
||||
Listener& get_listener() { return _listener;}
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -2046,3 +2046,7 @@ void RedWindow::init()
|
||||
#endif
|
||||
}
|
||||
|
||||
void RedWindow::cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user