Respect minimum size hints for floating windows. (#2508)
This commit introduces proper support for the minimum size on floating windows by ensuring that it is respected during mapping, later changes as well as resizes. Furthermore, this commit fixes minor issues with how the hints are handled during calculations. fixes #2436
This commit is contained in:
committed by
Michael Stapelberg
parent
f25c3d5e77
commit
a301396997
@ -929,54 +929,72 @@ static bool handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t stat
|
||||
|
||||
xcb_size_hints_t size_hints;
|
||||
|
||||
//CLIENT_LOG(client);
|
||||
|
||||
/* If the hints were already in this event, use them, if not, request them */
|
||||
if (reply != NULL)
|
||||
if (reply != NULL) {
|
||||
xcb_icccm_get_wm_size_hints_from_reply(&size_hints, reply);
|
||||
else
|
||||
} else {
|
||||
xcb_icccm_get_wm_normal_hints_reply(conn, xcb_icccm_get_wm_normal_hints_unchecked(conn, con->window->id), &size_hints, NULL);
|
||||
}
|
||||
|
||||
int win_width = con->window_rect.width;
|
||||
int win_height = con->window_rect.height;
|
||||
|
||||
if ((size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE)) {
|
||||
// TODO: Minimum size is not yet implemented
|
||||
DLOG("Minimum size: %d (width) x %d (height)\n", size_hints.min_width, size_hints.min_height);
|
||||
|
||||
con->window->min_width = size_hints.min_width;
|
||||
con->window->min_height = size_hints.min_height;
|
||||
}
|
||||
|
||||
if (con_is_floating(con)) {
|
||||
win_width = MAX(win_width, con->window->min_width);
|
||||
win_height = MAX(win_height, con->window->min_height);
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
if ((size_hints.flags & XCB_ICCCM_SIZE_HINT_P_RESIZE_INC)) {
|
||||
if (size_hints.width_inc > 0 && size_hints.width_inc < 0xFFFF)
|
||||
if (size_hints.width_inc > 0 && size_hints.width_inc < 0xFFFF) {
|
||||
if (con->window->width_increment != size_hints.width_inc) {
|
||||
con->window->width_increment = size_hints.width_inc;
|
||||
changed = true;
|
||||
}
|
||||
if (size_hints.height_inc > 0 && size_hints.height_inc < 0xFFFF)
|
||||
}
|
||||
|
||||
if (size_hints.height_inc > 0 && size_hints.height_inc < 0xFFFF) {
|
||||
if (con->window->height_increment != size_hints.height_inc) {
|
||||
con->window->height_increment = size_hints.height_inc;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed)
|
||||
if (changed) {
|
||||
DLOG("resize increments changed\n");
|
||||
}
|
||||
}
|
||||
|
||||
int base_width = 0, base_height = 0;
|
||||
bool has_base_size = false;
|
||||
int base_width = 0;
|
||||
int base_height = 0;
|
||||
|
||||
/* base_width/height are the desired size of the window.
|
||||
We check if either the program-specified size or the program-specified
|
||||
min-size is available */
|
||||
/* The base width / height is the desired size of the window. */
|
||||
if (size_hints.flags & XCB_ICCCM_SIZE_HINT_BASE_SIZE) {
|
||||
base_width = size_hints.base_width;
|
||||
base_height = size_hints.base_height;
|
||||
} else if (size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) {
|
||||
/* TODO: is this right? icccm says not */
|
||||
has_base_size = true;
|
||||
}
|
||||
|
||||
/* If the window didn't specify a base size, the ICCCM tells us to fall
|
||||
* back to the minimum size instead, if available. */
|
||||
if (!has_base_size && size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) {
|
||||
base_width = size_hints.min_width;
|
||||
base_height = size_hints.min_height;
|
||||
}
|
||||
|
||||
if (base_width != con->window->base_width ||
|
||||
base_height != con->window->base_height) {
|
||||
// TODO XXX Should we only do this is the base size is > 0?
|
||||
if (base_width != con->window->base_width || base_height != con->window->base_height) {
|
||||
con->window->base_width = base_width;
|
||||
con->window->base_height = base_height;
|
||||
|
||||
DLOG("client's base_height changed to %d\n", base_height);
|
||||
DLOG("client's base_width changed to %d\n", base_width);
|
||||
changed = true;
|
||||
@ -989,9 +1007,13 @@ static bool handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t stat
|
||||
goto render_and_return;
|
||||
}
|
||||
|
||||
/* XXX: do we really use rect here, not window_rect? */
|
||||
double width = con->rect.width - base_width;
|
||||
double height = con->rect.height - base_height;
|
||||
/* The ICCCM says to subtract the base size from the window size for aspect
|
||||
* ratio calculations. However, unlike determining the base size itself we
|
||||
* must not fall back to using the minimum size in this case according to
|
||||
* the ICCCM. */
|
||||
double width = win_width - base_width * has_base_size;
|
||||
double height = win_height - base_height * has_base_size;
|
||||
|
||||
/* Convert numerator/denominator to a double */
|
||||
double min_aspect = (double)size_hints.min_aspect_num / size_hints.min_aspect_den;
|
||||
double max_aspect = (double)size_hints.max_aspect_num / size_hints.min_aspect_den;
|
||||
@ -1000,8 +1022,9 @@ static bool handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t stat
|
||||
DLOG("width = %f, height = %f\n", width, height);
|
||||
|
||||
/* Sanity checks, this is user-input, in a way */
|
||||
if (max_aspect <= 0 || min_aspect <= 0 || height == 0 || (width / height) <= 0)
|
||||
if (max_aspect <= 0 || min_aspect <= 0 || height == 0 || (width / height) <= 0) {
|
||||
goto render_and_return;
|
||||
}
|
||||
|
||||
/* Check if we need to set proportional_* variables using the correct ratio */
|
||||
double aspect_ratio = 0.0;
|
||||
@ -1009,8 +1032,9 @@ static bool handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t stat
|
||||
aspect_ratio = min_aspect;
|
||||
} else if ((width / height) > max_aspect) {
|
||||
aspect_ratio = max_aspect;
|
||||
} else
|
||||
} else {
|
||||
goto render_and_return;
|
||||
}
|
||||
|
||||
if (fabs(con->window->aspect_ratio - aspect_ratio) > DBL_EPSILON) {
|
||||
con->window->aspect_ratio = aspect_ratio;
|
||||
@ -1018,8 +1042,10 @@ static bool handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t stat
|
||||
}
|
||||
|
||||
render_and_return:
|
||||
if (changed)
|
||||
if (changed) {
|
||||
tree_render();
|
||||
}
|
||||
|
||||
FREE(reply);
|
||||
return true;
|
||||
}
|
||||
|
Reference in New Issue
Block a user