stop button spam on lost focus

This commit is contained in:
David Rose 2012-01-15 17:01:20 +00:00
parent 6c34e0fb6c
commit 1968a30cd0
5 changed files with 81 additions and 208 deletions

View File

@ -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();
}

View File

@ -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<ButtonHandle> ButtonsHeld;
ButtonsHeld _buttons_held;
};
#include "graphicsWindowInputDevice.I"

View File

@ -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

View File

@ -27,9 +27,6 @@
#include <tchar.h>
#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

View File

@ -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