瀏覽代碼

Fix various window sizing issues on X11

rdb 10 年之前
父節點
當前提交
902bce01e9
共有 2 個文件被更改,包括 80 次插入58 次删除
  1. 78 58
      panda/src/x11display/x11GraphicsWindow.cxx
  2. 2 0
      panda/src/x11display/x11GraphicsWindow.h

+ 78 - 58
panda/src/x11display/x11GraphicsWindow.cxx

@@ -429,6 +429,7 @@ process_events() {
     // inner corner, anyway, but that means we need to fix
     // XConfigureWindow too.)
     properties.set_origin(configure_event.x, configure_event.y);
+    properties.set_size(configure_event.width, configure_event.height);
 
     if (_properties.get_fixed_size()) {
       // If the window properties indicate a fixed size only, undo
@@ -436,21 +437,15 @@ process_events() {
       // 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()) {
+      // managers.)
+      if (configure_event.width != _fixed_size.get_x() ||
+          configure_event.height != _fixed_size.get_y()) {
         XWindowChanges changes;
-        changes.width = current_props.get_x_size();
-        changes.height = current_props.get_y_size();
+        changes.width = _fixed_size.get_x();
+        changes.height = _fixed_size.get_y();
         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;
   }
@@ -494,16 +489,19 @@ set_properties_now(WindowProperties &properties) {
   x11GraphicsPipe *x11_pipe;
   DCAST_INTO_V(x11_pipe, _pipe);
 
-  // Handle fullscreen mode.
-  if (properties.has_fullscreen()) {
-    if (properties.get_fullscreen()) {
+  // We're either going into or out of fullscreen, or are in fullscreen
+  // and are changing the resolution.
+  bool is_fullscreen = _properties.has_fullscreen() && _properties.get_fullscreen();
+  bool want_fullscreen = properties.has_fullscreen() ? properties.get_fullscreen() : is_fullscreen;
+
+  if (is_fullscreen != want_fullscreen || (is_fullscreen && properties.has_size())) {
+    if (want_fullscreen) {
       if (_have_xrandr) {
 #ifdef HAVE_XRANDR
         XRRScreenConfiguration* conf = XRRGetScreenInfo(_display, x11_pipe->get_root());
-        if (_orig_size_id == (SizeID) -1) {
-          _orig_size_id = XRRConfigCurrentConfiguration(conf, &_orig_rotation);
-        }
-        int num_sizes, reqsizex, reqsizey, new_size_id = -1;
+        SizeID old_size_id = XRRConfigCurrentConfiguration(conf, &_orig_rotation);
+        SizeID new_size_id = (SizeID) -1;
+        int num_sizes = 0, reqsizex, reqsizey;
         if (properties.has_size()) {
           reqsizex = properties.get_x_size();
           reqsizey = properties.get_y_size();
@@ -519,16 +517,18 @@ set_properties_now(WindowProperties &properties) {
             new_size_id = i;
           }
         }
-        if (new_size_id == -1) {
+        if (new_size_id == (SizeID) -1) {
           x11display_cat.error()
             << "Videocard has no supported display resolutions at specified res ("
-            << reqsizex << " x " << reqsizey <<")\n";
-          _orig_size_id = -1;
+            << reqsizex << " x " << reqsizey << ")\n";
         } else {
-          if (new_size_id != _orig_size_id) {
+          if (new_size_id != old_size_id) {
+
             XRRSetScreenConfig(_display, conf, x11_pipe->get_root(), new_size_id, _orig_rotation, CurrentTime);
-          } else {
-            _orig_size_id = -1;
+            if (_orig_size_id == (SizeID) -1) {
+              // Remember the original resolution so we can switch back to it.
+              _orig_size_id = old_size_id;
+            }
           }
         }
 #endif
@@ -545,7 +545,7 @@ set_properties_now(WindowProperties &properties) {
       if (_have_xrandr && _orig_size_id != (SizeID) -1) {
         XRRScreenConfiguration* conf = XRRGetScreenInfo(_display, x11_pipe->get_root());
         XRRSetScreenConfig(_display, conf, x11_pipe->get_root(), _orig_size_id, _orig_rotation, CurrentTime);
-        _orig_size_id = -1;
+        _orig_size_id = (SizeID) -1;
       }
 #endif
       // Set the origin back to what it was
@@ -589,8 +589,7 @@ set_properties_now(WindowProperties &properties) {
   // on the fly.
 
   // We'll pass some property requests on as a window manager hint.
-  WindowProperties wm_properties = _properties;
-  wm_properties.add_properties(properties);
+  set_wm_properties(properties, true);
 
   // The window title may be changed by issuing another hint request.
   // Assume this will be honored.
@@ -617,6 +616,7 @@ set_properties_now(WindowProperties &properties) {
     changes.y = 0;
     value_mask |= CWX | CWY;
     properties.clear_origin();
+
   } else if (properties.has_origin()) {
     changes.x = properties.get_x_origin();
     changes.y = properties.get_y_origin();
@@ -625,10 +625,21 @@ set_properties_now(WindowProperties &properties) {
     properties.clear_origin();
   }
 
+  // This, too.  But we can't currently change out of fixed_size mode.
+  if (properties.has_fixed_size() && properties.get_fixed_size()) {
+    _properties.set_fixed_size(properties.get_fixed_size());
+    properties.clear_fixed_size();
+    _fixed_size = _properties.get_size();
+  }
+
   if (properties.has_size()) {
     changes.width = properties.get_x_size();
     changes.height = properties.get_y_size();
     value_mask |= (CWWidth | CWHeight);
+
+    if (_properties.get_fixed_size()) {
+      _fixed_size = properties.get_size();
+    }
     properties.clear_size();
   }
 
@@ -656,13 +667,6 @@ set_properties_now(WindowProperties &properties) {
     properties.clear_z_order();
   }
 
-  if (value_mask != 0) {
-    XReconfigureWMWindow(_display, _xwindow, _screen, value_mask, &changes);
-
-    // Don't draw anything until this is done reconfiguring.
-    _awaiting_configure = true;
-  }
-
   // We hide the cursor by setting it to an invisible pixmap.
   // We can also load a custom cursor from a file.
   if (properties.has_cursor_hidden() || properties.has_cursor_filename()) {
@@ -783,7 +787,14 @@ set_properties_now(WindowProperties &properties) {
     }
   }
 
-  set_wm_properties(wm_properties, true);
+  if (value_mask != 0) {
+    // We must call this after changing the WM properties, otherwise
+    // we may get misleading ConfigureNotify events in the wrong order.
+    XReconfigureWMWindow(_display, _xwindow, _screen, value_mask, &changes);
+
+    // Don't draw anything until this is done reconfiguring.
+    _awaiting_configure = true;
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -962,6 +973,11 @@ open_window() {
       << "failed to create X window.\n";
     return false;
   }
+
+  if (_properties.get_fixed_size()) {
+    _fixed_size = _properties.get_size();
+  }
+
   set_wm_properties(_properties, false);
 
   // We don't specify any fancy properties of the XIC.  It would be
@@ -1034,8 +1050,8 @@ set_wm_properties(const WindowProperties &properties, bool already_mapped) {
   XTextProperty window_name;
   XTextProperty *window_name_p = (XTextProperty *)NULL;
   if (properties.has_title()) {
-    char *name = (char *)properties.get_title().c_str();
-    if (XStringListToTextProperty(&name, 1, &window_name) != 0) {
+    const char *name = properties.get_title().c_str();
+    if (XStringListToTextProperty((char **)&name, 1, &window_name) != 0) {
       window_name_p = &window_name;
     }
   }
@@ -1056,18 +1072,19 @@ set_wm_properties(const WindowProperties &properties, bool already_mapped) {
         }
         size_hints_p->flags |= USPosition;
       }
+      LVecBase2i size = _properties.get_size();
       if (properties.has_size()) {
-        size_hints_p->width = properties.get_x_size();
-        size_hints_p->height = properties.get_y_size();
+        size = properties.get_size();
+        size_hints_p->width = size.get_x();
+        size_hints_p->height = size.get_y();
         size_hints_p->flags |= USSize;
-
-        if (properties.get_fixed_size()) {
-          size_hints_p->min_width = properties.get_x_size();
-          size_hints_p->min_height = properties.get_y_size();
-          size_hints_p->max_width = properties.get_x_size();
-          size_hints_p->max_height = properties.get_y_size();
-          size_hints_p->flags |= (PMinSize | PMaxSize);
-        }
+      }
+      if (properties.get_fixed_size()) {
+        size_hints_p->min_width = size.get_x();
+        size_hints_p->min_height = size.get_y();
+        size_hints_p->max_width = size.get_x();
+        size_hints_p->max_height = size.get_y();
+        size_hints_p->flags |= (PMinSize | PMaxSize);
       }
     }
   }
@@ -1107,18 +1124,21 @@ set_wm_properties(const WindowProperties &properties, bool already_mapped) {
   SetAction set_data[max_set_data];
   int next_set_data = 0;
 
-  if (properties.get_fullscreen()) {
-    // For a "fullscreen" request, we pass this through, hoping the
-    // window manager will support EWMH.
-    type_data[next_type_data++] = x11_pipe->_net_wm_window_type_fullscreen;
+  if (properties.has_fullscreen()) {
+    if (properties.get_fullscreen()) {
+      // For a "fullscreen" request, we pass this through, hoping the
+      // window manager will support EWMH.
+      type_data[next_type_data++] = x11_pipe->_net_wm_window_type_fullscreen;
+
+      // We also request it as a state.
+      state_data[next_state_data++] = x11_pipe->_net_wm_state_fullscreen;
+      // Don't ask me why this has to be 1/0 and not _net_wm_state_add.
+      // It doesn't seem to work otherwise.
+      set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_fullscreen, 1);
 
-    // We also request it as a state.
-    state_data[next_state_data++] = x11_pipe->_net_wm_state_fullscreen;
-    // Don't ask me why this has to be 1/0 and not _net_wm_state_add.
-    // It doesn't seem to work otherwise.
-    set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_fullscreen, 1);
-  } else {
-    set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_fullscreen, 0);
+    } else {
+      set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_fullscreen, 0);
+    }
   }
 
   // If we asked for a window without a border, there's no excellent

+ 2 - 0
panda/src/x11display/x11GraphicsWindow.h

@@ -96,6 +96,8 @@ protected:
   SizeID _orig_size_id;
 #endif
 
+  LVecBase2i _fixed_size;
+
   long _event_mask;
   bool _awaiting_configure;
   bool _dga_mouse_enabled;