Browse Source

Partially fix excessive event spam when resizing windows

rdb 11 years ago
parent
commit
083e160f89
2 changed files with 66 additions and 40 deletions
  1. 10 3
      direct/src/showbase/ShowBase.py
  2. 56 37
      panda/src/x11display/x11GraphicsWindow.cxx

+ 10 - 3
direct/src/showbase/ShowBase.py

@@ -372,6 +372,7 @@ class ShowBase(DirectObject.DirectObject):
         # Now hang a hook on the window-event from Panda.  This allows
         # us to detect when the user resizes, minimizes, or closes the
         # main window.
+        self.__prevWindowProperties = None
         self.accept('window-event', self.windowEvent)
 
         # Transition effects (fade, iris, etc)
@@ -2614,9 +2615,15 @@ class ShowBase(DirectObject.DirectObject):
             return Task.cont
 
     def windowEvent(self, win):
-        if win == self.win:
-            properties = win.getProperties()
-            self.notify.info("Got window event: %s" % (repr(properties)))
+        if win != self.win:
+            # This event isn't about our window.
+            return
+
+        properties = win.getProperties()
+        if properties != self.__prevWindowProperties:
+            self.__prevWindowProperties = properties
+
+            self.notify.debug("Got window event: %s" % (repr(properties)))
             if not properties.getOpen():
                 # If the user closes the main window, we should exit.
                 self.notify.info("User closed main window.")

+ 56 - 37
panda/src/x11display/x11GraphicsWindow.cxx

@@ -263,6 +263,12 @@ process_events() {
   XKeyEvent keyrelease_event;
   bool got_keyrelease_event = false;
 
+  XConfigureEvent configure_event;
+  bool got_configure_event = false;
+
+  WindowProperties properties;
+  bool changed_properties = false;
+
   while (XCheckIfEvent(_display, &event, check_event, (char *)this)) {
     if (XFilterEvent(&event, None)) {
       continue;
@@ -295,7 +301,6 @@ process_events() {
       }
     }
 
-    WindowProperties properties;
     ButtonHandle button;
 
     switch (event.type) {
@@ -303,38 +308,11 @@ process_events() {
       break;
 
     case ConfigureNotify:
-      _awaiting_configure = false;
-
-      // Is this the inner corner or the outer corner?  The Xlib docs
-      // say it should be the outer corner, but it appears to be the
-      // inner corner on my own implementation, which is inconsistent
-      // with XConfigureWindow.  (Panda really wants to work with the
-      // inner corner, anyway, but that means we need to fix
-      // XConfigureWindow too.)
-      properties.set_origin(event.xconfigure.x, event.xconfigure.y);
-
-      if (_properties.get_fixed_size()) {
-        // If the window properties indicate a fixed size only, undo
-        // any attempt by the user to change them.  In X, there
-        // doesn't appear to be a way to universally disallow this
-        // directly (although we do set the min_size and max_size to
-        // the same value, which seems to work for most window
-        // managers.)
-        WindowProperties current_props = get_properties();
-        if (event.xconfigure.width != current_props.get_x_size() ||
-            event.xconfigure.height != current_props.get_y_size()) {
-          XWindowChanges changes;
-          changes.width = current_props.get_x_size();
-          changes.height = current_props.get_y_size();
-          int value_mask = (CWWidth | CWHeight);
-          XConfigureWindow(_display, _xwindow, value_mask, &changes);
-        }
-
-      } else {
-        // A normal window may be resized by the user at will.
-        properties.set_size(event.xconfigure.width, event.xconfigure.height);
-      }
-      system_changed_properties(properties);
+      // When resizing or moving the window, multiple ConfigureNotify
+      // events may be sent in rapid succession.  We only respond to
+      // the last one.
+      configure_event = event.xconfigure;
+      got_configure_event = true;
       break;
 
     case ButtonPress:
@@ -391,23 +369,23 @@ process_events() {
 
     case FocusIn:
       properties.set_foreground(true);
-      system_changed_properties(properties);
+      changed_properties = true;
       break;
 
     case FocusOut:
       _input_devices[0].focus_lost();
       properties.set_foreground(false);
-      system_changed_properties(properties);
+      changed_properties = true;
       break;
 
     case UnmapNotify:
       properties.set_minimized(true);
-      system_changed_properties(properties);
+      changed_properties = true;
       break;
 
     case MapNotify:
       properties.set_minimized(false);
-      system_changed_properties(properties);
+      changed_properties = true;
 
       // Auto-focus the window when it is mapped.
       XSetInputFocus(_display, _xwindow, RevertToPointerRoot, CurrentTime);
@@ -449,6 +427,47 @@ process_events() {
     }
   }
 
+  if (got_configure_event) {
+    // Now handle the last configure event we found.
+    _awaiting_configure = false;
+
+    // Is this the inner corner or the outer corner?  The Xlib docs
+    // say it should be the outer corner, but it appears to be the
+    // inner corner on my own implementation, which is inconsistent
+    // with XConfigureWindow.  (Panda really wants to work with the
+    // inner corner, anyway, but that means we need to fix
+    // XConfigureWindow too.)
+    properties.set_origin(configure_event.x, configure_event.y);
+
+    if (_properties.get_fixed_size()) {
+      // If the window properties indicate a fixed size only, undo
+      // any attempt by the user to change them.  In X, there
+      // doesn't appear to be a way to universally disallow this
+      // directly (although we do set the min_size and max_size to
+      // the same value, which seems to work for most window
+      // managers.)  Incidentally, this also works to force my
+      // tiling window manager into 'floating' mode.
+      WindowProperties current_props = get_properties();
+      if (configure_event.width != current_props.get_x_size() ||
+          configure_event.height != current_props.get_y_size()) {
+        XWindowChanges changes;
+        changes.width = current_props.get_x_size();
+        changes.height = current_props.get_y_size();
+        int value_mask = (CWWidth | CWHeight);
+        XConfigureWindow(_display, _xwindow, value_mask, &changes);
+      }
+
+    } else {
+      // A normal window may be resized by the user at will.
+      properties.set_size(configure_event.width, configure_event.height);
+    }
+    changed_properties = true;
+  }
+
+  if (changed_properties) {
+    system_changed_properties(properties);
+  }
+
   if (got_keyrelease_event) {
     // This keyrelease event is not immediately followed by a
     // matching keypress event, so it's a genuine release.