diff --git a/panda/src/display/graphicsWindowInputDevice.cxx b/panda/src/display/graphicsWindowInputDevice.cxx index 6d8033ca6e..4891499ddf 100644 --- a/panda/src/display/graphicsWindowInputDevice.cxx +++ b/panda/src/display/graphicsWindowInputDevice.cxx @@ -291,6 +291,7 @@ void GraphicsWindowInputDevice:: button_down(ButtonHandle button, double time) { LightMutexHolder holder(_lock); _button_events.push_back(ButtonEvent(button, ButtonEvent::T_down, time)); + _buttons_held.insert(button); } //////////////////////////////////////////////////////////////////// @@ -304,7 +305,9 @@ button_down(ButtonHandle button, double time) { void GraphicsWindowInputDevice:: button_resume_down(ButtonHandle button, double time) { LightMutexHolder holder(_lock); - _button_events.push_back(ButtonEvent(button, ButtonEvent::T_resume_down, time)); + _button_events.push_back(ButtonEvent(button, ButtonEvent::T_resume_down, time) +); + _buttons_held.insert(button); } //////////////////////////////////////////////////////////////////// @@ -316,6 +319,7 @@ void GraphicsWindowInputDevice:: button_up(ButtonHandle button, double time) { LightMutexHolder holder(_lock); _button_events.push_back(ButtonEvent(button, ButtonEvent::T_up, time)); + _buttons_held.erase(button); } //////////////////////////////////////////////////////////////////// @@ -346,3 +350,24 @@ candidate(const wstring &candidate_string, size_t highlight_start, highlight_start, highlight_end, cursor_pos)); } + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindowInputDevice::focus_lost +// Access: Public +// Description: This should be called when the window focus is lost, +// so that we may miss upcoming button events +// (especially "up" events) for the next period of time. +// It generates keyboard and mouse "up" events for those +// buttons that we previously sent unpaired "down" +// events, so that the Panda application will believe +// all buttons are now released. +//////////////////////////////////////////////////////////////////// +void GraphicsWindowInputDevice:: +focus_lost(double time) { + LightMutexHolder holder(_lock); + ButtonsHeld::iterator bi; + for (bi = _buttons_held.begin(); bi != _buttons_held.end(); ++bi) { + _button_events.push_back(ButtonEvent(*bi, ButtonEvent::T_up, time)); + } + _buttons_held.clear(); +} diff --git a/panda/src/display/graphicsWindowInputDevice.h b/panda/src/display/graphicsWindowInputDevice.h index a72770d07e..282735fbc7 100644 --- a/panda/src/display/graphicsWindowInputDevice.h +++ b/panda/src/display/graphicsWindowInputDevice.h @@ -79,7 +79,8 @@ PUBLISHED: void button_up(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time()); void keystroke(int keycode, double time = ClockObject::get_global_clock()->get_frame_time()); void candidate(const wstring &candidate_string, size_t highlight_start, - size_t higlight_end, size_t cursor_pos); + size_t highlight_end, size_t cursor_pos); + void focus_lost(double time = ClockObject::get_global_clock()->get_frame_time()); INLINE void set_pointer_in_window(int x, int y, double time = ClockObject::get_global_clock()->get_frame_time()); INLINE void set_pointer_out_of_window(double time = ClockObject::get_global_clock()->get_frame_time()); @@ -120,6 +121,8 @@ private: ButtonEvents _button_events; PT(PointerEventList) _pointer_events; + typedef pset ButtonsHeld; + ButtonsHeld _buttons_held; }; #include "graphicsWindowInputDevice.I" diff --git a/panda/src/windisplay/winGraphicsWindow.I b/panda/src/windisplay/winGraphicsWindow.I index 57cc1e596e..094e96efcd 100644 --- a/panda/src/windisplay/winGraphicsWindow.I +++ b/panda/src/windisplay/winGraphicsWindow.I @@ -13,45 +13,6 @@ //////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////// -// Function: WinGraphicsWindow::handle_keypress -// Access: Private -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void WinGraphicsWindow:: -handle_keypress(ButtonHandle key, int x, int y, double time) { - _input_devices[0].set_pointer_in_window(x, y); - if (key != ButtonHandle::none()) { - _input_devices[0].button_down(key, time); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: WinGraphicsWindow::handle_keyresume -// Access: Private -// Description: Indicates we detected a key was already down when the -// focus is restored to the window. Mainly useful for -// tracking the state of modifier keys. -//////////////////////////////////////////////////////////////////// -INLINE void WinGraphicsWindow:: -handle_keyresume(ButtonHandle key, double time) { - if (key != ButtonHandle::none()) { - _input_devices[0].button_resume_down(key, time); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: WinGraphicsWindow::handle_keyrelease -// Access: Private -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void WinGraphicsWindow:: -handle_keyrelease(ButtonHandle key, double time) { - if (key != ButtonHandle::none()) { - _input_devices[0].button_up(key, time); - } -} - //////////////////////////////////////////////////////////////////// // Function: WinGraphicsWindow::translate_mouse // Access: Private diff --git a/panda/src/windisplay/winGraphicsWindow.cxx b/panda/src/windisplay/winGraphicsWindow.cxx index ce782bec37..7a7bd33fc3 100644 --- a/panda/src/windisplay/winGraphicsWindow.cxx +++ b/panda/src/windisplay/winGraphicsWindow.cxx @@ -27,9 +27,6 @@ #include -#define WANT_NEW_FOCUS_MANAGMENT - - TypeHandle WinGraphicsWindow::_type_handle; TypeHandle WinGraphicsWindow::WinWindowHandle::_type_handle; @@ -99,7 +96,6 @@ WinGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, _tracking_mouse_leaving = false; _maximized = false; _cursor = 0; - memset(_keyboard_state, 0, sizeof(BYTE) * num_virtual_keys); _lost_keypresses = false; _lshift_down = false; _rshift_down = false; @@ -1977,80 +1973,12 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { break; case WM_KILLFOCUS: - if (windisplay_cat.is_debug()) - { - windisplay_cat.debug() - << "killfocus\n"; - } - -#ifndef WANT_NEW_FOCUS_MANAGMENT - if (!_lost_keypresses) - { - // Record the current state of the keyboard when the focus is - // lost, so we can check it for changes when we regain focus. - GetKeyboardState(_keyboard_state); - if (windisplay_cat.is_debug()) { - // Report the set of keys that are held down at the time of - // the killfocus event. - for (int i = 0; i < num_virtual_keys; i++) - { - if (i != VK_SHIFT && i != VK_CONTROL && i != VK_MENU) - { - if ((_keyboard_state[i] & 0x80) != 0) - { - windisplay_cat.debug() - << "on killfocus, key is down: " << i - << " (" << lookup_key(i) << ")\n"; - } - } - } - } - - if (!hold_keys_across_windows) - { - // If we don't want to remember the keystate while the - // window focus is lost, then generate a keyup event - // right now for each key currently held. - double message_time = get_message_time(); - for (int i = 0; i < num_virtual_keys; i++) - { - if (i != VK_SHIFT && i != VK_CONTROL && i != VK_MENU) - { - if ((_keyboard_state[i] & 0x80) != 0) - { - handle_keyrelease(lookup_key(i), message_time); - _keyboard_state[i] &= ~0x80; - } - } - } - } - - // Now set the flag indicating that some keypresses from now - // on may be lost. - _lost_keypresses = true; - } -#else // WANT_NEW_FOCUS_MANAGMENT - { - double message_time = get_message_time(); - int i; - for (i = 0; i < num_virtual_keys; i++) { - ButtonHandle bh = lookup_key(i); - if(bh != ButtonHandle::none()) { - handle_keyrelease(bh,message_time); - } - } - memset(_keyboard_state, 0, sizeof(BYTE) * num_virtual_keys); - - // Also up the mouse buttons. - for (i = 0; i < MouseButton::num_mouse_buttons; ++i) { - handle_keyrelease(MouseButton::button(i), message_time); - } - handle_keyrelease(MouseButton::wheel_up(), message_time); - handle_keyrelease(MouseButton::wheel_down(), message_time); - - _lost_keypresses = true; + if (windisplay_cat.is_debug()) { + windisplay_cat.debug() + << "killfocus\n"; } -#endif // WANT_NEW_FOCUS_MANAGMENT + + _input_devices[0].focus_lost(get_message_time()); properties.set_foreground(false); system_changed_properties(properties); break; @@ -2186,81 +2114,11 @@ process_1_event() { //////////////////////////////////////////////////////////////////// void WinGraphicsWindow:: resend_lost_keypresses() { - _lost_keypresses = false; - return; nassertv(_lost_keypresses); - if (windisplay_cat.is_debug()) { - windisplay_cat.debug() - << "resending lost keypresses\n"; - } + // This is now a no-op. Not sure we really want to generate new + // "down" or "resume" events for keys that were held while the + // window focus is restored. - BYTE new_keyboard_state[num_virtual_keys]; - GetKeyboardState(new_keyboard_state); - double message_time = get_message_time(); - -#ifndef WANT_NEW_FOCUS_MANAGMENT - for (int i = 0; i < num_virtual_keys; i++) { - // Filter out these particular three. We don't want to test - // these, because these are virtual duplicates for - // VK_LSHIFT/VK_RSHIFT, etc.; and the left/right equivalent is - // also in the table. If we respect both VK_LSHIFT as well as - // VK_SHIFT, we'll generate two keyboard messages when - // VK_LSHIFT changes state. - if (i != VK_SHIFT && i != VK_CONTROL && i != VK_MENU) { - if (((new_keyboard_state[i] ^ _keyboard_state[i]) & 0x80) != 0) { - // This key has changed state. - if ((new_keyboard_state[i] & 0x80) != 0) { - // The key is now held down. - if (windisplay_cat.is_debug()) { - windisplay_cat.debug() - << "key has gone down: " << i << " (" << lookup_key(i) << ")\n"; - } - - // Roger - //handle_keyresume(lookup_key(i), message_time); - // resume does not seem to work and sending the pointer position seems to - // weird ot some cursor controls - ButtonHandle key = lookup_key(i); - if (key != ButtonHandle::none()) - _input_devices[0].button_down(key, message_time); - - - } else { - // The key is now released. - if (windisplay_cat.is_debug()) { - windisplay_cat.debug() - << "key has gone up: " << i << " (" << lookup_key(i) << ")\n"; - } - handle_keyrelease(lookup_key(i), message_time); - } - } else { - // This key is in the same state. - if (windisplay_cat.is_debug()) { - if ((new_keyboard_state[i] & 0x80) != 0) { - windisplay_cat.debug() - << "key is still down: " << i << " (" << lookup_key(i) << ")\n"; - } - } - } - } - } -#else // WANT_NEW_FOCUS_MANAGMENT - for (int i = 0; i < num_virtual_keys; i++) - { - if ((new_keyboard_state[i] & 0x80) != 0) - { - ButtonHandle key = lookup_key(i); - if (key != ButtonHandle::none()) - if (windisplay_cat.is_debug()) { - windisplay_cat.debug() - << "resending key: " << " (" << key << ")\n"; - } - _input_devices[0].button_down(key, message_time); - } - } -#endif // WANT_NEW_FOCUS_MANAGMENT - - // Keypresses are no longer lost. _lost_keypresses = false; } @@ -2402,6 +2260,45 @@ show_error_message(DWORD message_id) { LocalFree(message_buffer); } +//////////////////////////////////////////////////////////////////// +// Function: WinGraphicsWindow::handle_keypress +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +void WinGraphicsWindow:: +handle_keypress(ButtonHandle key, int x, int y, double time) { + _input_devices[0].set_pointer_in_window(x, y); + if (key != ButtonHandle::none()) { + _input_devices[0].button_down(key, time); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: WinGraphicsWindow::handle_keyresume +// Access: Private +// Description: Indicates we detected a key was already down when the +// focus is restored to the window. Mainly useful for +// tracking the state of modifier keys. +//////////////////////////////////////////////////////////////////// +void WinGraphicsWindow:: +handle_keyresume(ButtonHandle key, double time) { + if (key != ButtonHandle::none()) { + _input_devices[0].button_resume_down(key, time); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: WinGraphicsWindow::handle_keyrelease +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +void WinGraphicsWindow:: +handle_keyrelease(ButtonHandle key, double time) { + if (key != ButtonHandle::none()) { + _input_devices[0].button_up(key, time); + } +} + //////////////////////////////////////////////////////////////////// // Function: WinGraphicsWindow::lookup_key // Access: Private diff --git a/panda/src/windisplay/winGraphicsWindow.h b/panda/src/windisplay/winGraphicsWindow.h index da88c71464..2becff96b4 100644 --- a/panda/src/windisplay/winGraphicsWindow.h +++ b/panda/src/windisplay/winGraphicsWindow.h @@ -127,9 +127,9 @@ private: static void process_1_event(); - INLINE void handle_keypress(ButtonHandle key, int x, int y, double time); - INLINE void handle_keyresume(ButtonHandle key, double time); - INLINE void handle_keyrelease(ButtonHandle key, double time); + void handle_keypress(ButtonHandle key, int x, int y, double time); + void handle_keyresume(ButtonHandle key, double time); + void handle_keyrelease(ButtonHandle key, double time); ButtonHandle lookup_key(WPARAM wparam) const; INLINE int translate_mouse(int pos) const; INLINE void set_cursor_in_window(); @@ -138,6 +138,7 @@ private: INLINE static double get_message_time(); void resend_lost_keypresses(); + void release_all_buttons(); static void update_cursor_window(WinGraphicsWindow *to_window); static void hide_or_show_cursor(bool hide_cursor); @@ -160,20 +161,6 @@ private: HCURSOR _cursor; DEVMODE _fullscreen_display_mode; - // This is used to remember the state of the keyboard when keyboard - // focus is lost. - enum { num_virtual_keys = 256 }; - // You might be wondering why the above is an enum. Originally the line - // read "static const int num_virtual_keys = 256" - // but in trying to support the MSVC6 compiler, we found that you - // were not allowed to define the value of a const within a class like - // that. Defining the value outside the class helps, but then we can't - // use the value to define the length of the _keyboard_state array, and - // also it creates multiply defined symbol errors when you link, because - // other files include this header file. This enum is a clever solution - // to work around the problem. - - BYTE _keyboard_state[num_virtual_keys]; bool _lost_keypresses; // These are used to store the status of the individual left and right