- /* obey size increments */
- if (focused_con->window != NULL && (focused_con->window->height_increment || focused_con->window->width_increment)) {
- Rect border_rect = con_border_style_rect(focused_con);
-
- /* We have to do the opposite calculations that render_con() do
- * to get the exact size we want. */
- border_rect.width = -border_rect.width;
- border_rect.width += 2 * focused_con->border_width;
- border_rect.height = -border_rect.height;
- border_rect.height += 2 * focused_con->border_width;
- if (con_border_style(focused_con) == BS_NORMAL)
- border_rect.height += render_deco_height();
-
- if (focused_con->window->height_increment &&
- floating_con->rect.height >= focused_con->window->base_height + border_rect.height) {
- floating_con->rect.height -= focused_con->window->base_height + border_rect.height;
- floating_con->rect.height -= floating_con->rect.height % focused_con->window->height_increment;
- floating_con->rect.height += focused_con->window->base_height + border_rect.height;
+ Rect border_rect = con_border_style_rect(focused_con);
+ /* We have to do the opposite calculations that render_con() do
+ * to get the exact size we want. */
+ border_rect.width = -border_rect.width;
+ border_rect.width += 2 * focused_con->border_width;
+ border_rect.height = -border_rect.height;
+ border_rect.height += 2 * focused_con->border_width;
+ if (con_border_style(focused_con) == BS_NORMAL) {
+ border_rect.height += render_deco_height();
+ }
+
+ i3Window *window = focused_con->window;
+ if (window != NULL) {
+ /* ICCCM says: If a base size is not provided, the minimum size is to be used in its place
+ * and vice versa. */
+ int min_width = (window->min_width ? window->min_width : window->base_width);
+ int min_height = (window->min_height ? window->min_height : window->base_height);
+ int base_width = (window->base_width ? window->base_width : window->min_width);
+ int base_height = (window->base_height ? window->base_height : window->min_height);
+
+ if (min_width) {
+ floating_con->rect.width -= border_rect.width;
+ floating_con->rect.width = max(floating_con->rect.width, min_width);
+ floating_con->rect.width += border_rect.width;
+ }
+
+ if (min_height) {
+ floating_con->rect.height -= border_rect.height;
+ floating_con->rect.height = max(floating_con->rect.height, min_height);
+ floating_con->rect.height += border_rect.height;
+ }
+
+ if (window->max_width) {
+ floating_con->rect.width -= border_rect.width;
+ floating_con->rect.width = min(floating_con->rect.width, window->max_width);
+ floating_con->rect.width += border_rect.width;
+ }
+
+ if (window->max_height) {
+ floating_con->rect.height -= border_rect.height;
+ floating_con->rect.height = min(floating_con->rect.height, window->max_height);
+ floating_con->rect.height += border_rect.height;
+ }
+
+ /* Obey the aspect ratio, if any, unless we are in fullscreen mode.
+ *
+ * The spec isn’t explicit on whether the aspect ratio hints should be
+ * respected during fullscreen mode. Other WMs such as Openbox don’t do
+ * that, and this post suggests that this is the correct way to do it:
+ * https://mail.gnome.org/archives/wm-spec-list/2003-May/msg00007.html
+ *
+ * Ignoring aspect ratio during fullscreen was necessary to fix MPlayer
+ * subtitle rendering, see https://bugs.i3wm.org/594 */
+ const double min_ar = window->min_aspect_ratio;
+ const double max_ar = window->max_aspect_ratio;
+ if (floating_con->fullscreen_mode == CF_NONE && (min_ar > 0 || max_ar > 0)) {
+ /* 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 = floating_con->rect.width - window->base_width - border_rect.width;
+ double height = floating_con->rect.height - window->base_height - border_rect.height;
+ const double ar = (double)width / (double)height;
+ double new_ar = -1;
+ if (min_ar > 0 && ar < min_ar) {
+ new_ar = min_ar;
+ } else if (max_ar > 0 && ar > max_ar) {
+ new_ar = max_ar;
+ }
+ if (new_ar > 0) {
+ if (prefer_height) {
+ width = round(height * new_ar);
+ height = round(width / new_ar);
+ } else {
+ height = round(width / new_ar);
+ width = round(height * new_ar);
+ }
+ floating_con->rect.width = width + window->base_width + border_rect.width;
+ floating_con->rect.height = height + window->base_height + border_rect.height;
+ }
+ }
+
+ if (window->height_increment &&
+ floating_con->rect.height >= base_height + border_rect.height) {
+ floating_con->rect.height -= base_height + border_rect.height;
+ floating_con->rect.height -= floating_con->rect.height % window->height_increment;
+ floating_con->rect.height += base_height + border_rect.height;