Browse Source

stop button spam on lost focus

David Rose 14 years ago
parent
commit
1968a30cd0

+ 26 - 1
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();
+}

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

+ 0 - 39
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

+ 47 - 150
panda/src/windisplay/winGraphicsWindow.cxx

@@ -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";
-  }
-
-  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);
-
+  // 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.
 
-        } 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

+ 4 - 17
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