From 902bce01e972b20abd7172503078ef93be066ed9 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 22 Aug 2015 19:16:21 +0200 Subject: [PATCH] Fix various window sizing issues on X11 --- panda/src/x11display/x11GraphicsWindow.cxx | 136 ++++++++++++--------- panda/src/x11display/x11GraphicsWindow.h | 2 + 2 files changed, 80 insertions(+), 58 deletions(-) diff --git a/panda/src/x11display/x11GraphicsWindow.cxx b/panda/src/x11display/x11GraphicsWindow.cxx index 019ab05f05..82a1180cf3 100644 --- a/panda/src/x11display/x11GraphicsWindow.cxx +++ b/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); - } else { - set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_fullscreen, 0); + // 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); + } } // If we asked for a window without a border, there's no excellent diff --git a/panda/src/x11display/x11GraphicsWindow.h b/panda/src/x11display/x11GraphicsWindow.h index 9fc7210f60..b8c79c8a86 100644 --- a/panda/src/x11display/x11GraphicsWindow.h +++ b/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;