David Rose 22 лет назад
Родитель
Сommit
106913d722
2 измененных файлов с 109 добавлено и 30 удалено
  1. 105 30
      panda/src/glxdisplay/glxGraphicsWindow.cxx
  2. 4 0
      panda/src/glxdisplay/glxGraphicsWindow.h

+ 105 - 30
panda/src/glxdisplay/glxGraphicsWindow.cxx

@@ -162,11 +162,41 @@ process_events() {
   }
 
   XEvent event;
+  XKeyEvent keyrelease_event;
+  bool got_keyrelease_event = false;
+
   while (XCheckIfEvent(_display, &event, check_event, (char *)this)) {
     if (XFilterEvent(&event, None)) {
       continue;
     }
 
+    if (got_keyrelease_event) {
+      // If a keyrelease event is immediately followed by a matching
+      // keypress event, that's just key repeat and we should treat
+      // the two events accordingly.  It would be nice if X provided a
+      // way to differentiate between keyrepeat and explicit
+      // keypresses more generally.
+      got_keyrelease_event = false;
+
+      if (event.type == KeyPress &&
+          event.xkey.keycode == keyrelease_event.keycode &&
+          (event.xkey.time - keyrelease_event.time <= 1)) {
+        // In particular, we only generate down messages for the
+        // repeated keys, not down-and-up messages.
+        handle_keystroke(event.xkey);
+
+        // We thought about not generating the keypress event, but we
+        // need that repeat for backspace.  Rethink later.
+        handle_keypress(event.xkey);
+        continue;
+
+      } else {
+        // This keyrelease event is not immediately followed by a
+        // matching keypress event, so it's a genuine release.
+        handle_keyrelease(keyrelease_event);
+      }
+    }
+
     WindowProperties properties;
     ButtonHandle button;
 
@@ -198,39 +228,16 @@ process_events() {
       break;
 
     case KeyPress:
-      {
-        _input_devices[0].set_pointer_in_window(event.xkey.x, event.xkey.y);
-
-        // First, get the keystroke as a wide-character sequence.
-        static const int buffer_size = 256;
-        wchar_t buffer[buffer_size];
-        Status status;
-        int len = XwcLookupString(_ic, &event.xkey, buffer, buffer_size, NULL,
-                                  &status);
-        if (status == XBufferOverflow) {
-          glxdisplay_cat.error()
-            << "Overflowed input buffer.\n";
-        }
-
-        // Now each of the returned wide characters represents a
-        // keystroke.
-        for (int i = 0; i < len; i++) {
-          _input_devices[0].keystroke(buffer[i]);
-        }
-
-        // Now get the raw unshifted button.
-        ButtonHandle button = get_button(&event.xkey);
-        if (button != ButtonHandle::none()) {
-          _input_devices[0].button_down(button);
-        }
-      }
+      handle_keystroke(event.xkey);
+      handle_keypress(event.xkey);
       break;
 
     case KeyRelease:
-      button = get_button(&event.xkey);
-      if (button != ButtonHandle::none()) {
-        _input_devices[0].button_up(button);
-      }
+      // The KeyRelease can't be processed immediately, because we
+      // have to check first if it's immediately followed by a
+      // matching KeyPress event.
+      keyrelease_event = event.xkey;
+      got_keyrelease_event = true;
       break;
 
     case EnterNotify:
@@ -287,6 +294,12 @@ process_events() {
         << "unhandled X event type " << event.type << "\n";
     }
   }
+
+  if (got_keyrelease_event) {
+    // This keyrelease event is not immediately followed by a
+    // matching keypress event, so it's a genuine release.
+    handle_keyrelease(keyrelease_event);
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -597,6 +610,68 @@ setup_colormap(XVisualInfo *visual) {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsWindow::handle_keystroke
+//       Access: Private
+//  Description: Generates a keystroke corresponding to the indicated
+//               X KeyPress event.
+////////////////////////////////////////////////////////////////////
+void glxGraphicsWindow::
+handle_keystroke(XKeyEvent &event) {
+  _input_devices[0].set_pointer_in_window(event.x, event.y);
+
+  // First, get the keystroke as a wide-character sequence.
+  static const int buffer_size = 256;
+  wchar_t buffer[buffer_size];
+  Status status;
+  int len = XwcLookupString(_ic, &event, buffer, buffer_size, NULL,
+                            &status);
+  if (status == XBufferOverflow) {
+    glxdisplay_cat.error()
+      << "Overflowed input buffer.\n";
+  }
+  
+  // Now each of the returned wide characters represents a
+  // keystroke.
+  for (int i = 0; i < len; i++) {
+    _input_devices[0].keystroke(buffer[i]);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsWindow::handle_keypress
+//       Access: Private
+//  Description: Generates a keypress corresponding to the indicated
+//               X KeyPress event.
+////////////////////////////////////////////////////////////////////
+void glxGraphicsWindow::
+handle_keypress(XKeyEvent &event) {
+  _input_devices[0].set_pointer_in_window(event.x, event.y);
+
+  // Now get the raw unshifted button.
+  ButtonHandle button = get_button(&event);
+  if (button != ButtonHandle::none()) {
+    _input_devices[0].button_down(button);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsWindow::handle_keyrelease
+//       Access: Private
+//  Description: Generates a keyrelease corresponding to the indicated
+//               X KeyRelease event.
+////////////////////////////////////////////////////////////////////
+void glxGraphicsWindow::
+handle_keyrelease(XKeyEvent &event) {
+  _input_devices[0].set_pointer_in_window(event.x, event.y);
+
+  // Now get the raw unshifted button.
+  ButtonHandle button = get_button(&event);
+  if (button != ButtonHandle::none()) {
+    _input_devices[0].button_up(button);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: glxGraphicsWindow::get_button
 //       Access: Private

+ 4 - 0
panda/src/glxdisplay/glxGraphicsWindow.h

@@ -56,6 +56,10 @@ private:
   void set_wm_properties(const WindowProperties &properties);
 
   void setup_colormap(XVisualInfo *visual);
+  void handle_keystroke(XKeyEvent &event);
+  void handle_keypress(XKeyEvent &event);
+  void handle_keyrelease(XKeyEvent &event);
+
   ButtonHandle get_button(XKeyEvent *key_event);
 
   static Bool check_event(Display *display, XEvent *event, char *arg);