Fix various window sizing issues on X11

This commit is contained in:
rdb 2015-08-22 19:16:21 +02:00
parent eecded05bd
commit 902bce01e9
2 changed files with 80 additions and 58 deletions

View File

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

View File

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