Skip to content
This repository has been archived by the owner on Apr 18, 2023. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'vanilla/next' into gaps-next
Browse files Browse the repository at this point in the history
  • Loading branch information
Airblader committed Nov 17, 2018
2 parents 0fb51fd + a080551 commit bfba56b
Show file tree
Hide file tree
Showing 15 changed files with 342 additions and 267 deletions.
3 changes: 2 additions & 1 deletion include/data.h
Expand Up @@ -497,7 +497,8 @@ struct Window {
int max_height;

/* aspect ratio from WM_NORMAL_HINTS (MPlayer uses this for example) */
double aspect_ratio;
double min_aspect_ratio;
double max_aspect_ratio;
};

/**
Expand Down
15 changes: 10 additions & 5 deletions include/floating.h
Expand Up @@ -94,12 +94,17 @@ void floating_drag_window(Con *con, const xcb_button_press_event_t *event);
void floating_resize_window(Con *con, const bool proportional, const xcb_button_press_event_t *event);

/**
* Called when a floating window is created or resized.
* This function resizes the window if its size is higher or lower than the
* configured maximum/minimum size, respectively.
* Called when a floating window is created or resized. This function resizes
* the window if its size is higher or lower than the configured maximum/minimum
* size, respectively or when adjustments are needed to conform to the
* configured size increments or aspect ratio limits.
*
* When prefer_height is true and the window needs to be resized because of the
* configured aspect ratio, the width is adjusted first, preserving the previous
* height.
*
*/
void floating_check_size(Con *floating_con);
void floating_check_size(Con *floating_con, bool prefer_height);

/**
* This is the return value of a drag operation like drag_pointer.
Expand Down Expand Up @@ -152,7 +157,7 @@ bool floating_reposition(Con *con, Rect newrect);
* window's size hints.
*
*/
void floating_resize(Con *floating_con, int x, int y);
void floating_resize(Con *floating_con, uint32_t x, uint32_t y);

/**
* Fixes the coordinates of the floating window whenever the window gets
Expand Down
2 changes: 1 addition & 1 deletion include/render.h
Expand Up @@ -40,7 +40,7 @@ typedef struct render_params {
* updated in X11.
*
*/
void render_con(Con *con, bool render_fullscreen, bool already_inset);
void render_con(Con *con, bool already_inset);

/**
* Returns the height for the decorations
Expand Down
6 changes: 6 additions & 0 deletions include/window.h
Expand Up @@ -70,6 +70,12 @@ void window_update_role(i3Window *win, xcb_get_property_reply_t *prop, bool befo
*/
void window_update_type(i3Window *window, xcb_get_property_reply_t *reply);

/**
* Updates the WM_NORMAL_HINTS
*
*/
bool window_update_normal_hints(i3Window *win, xcb_get_property_reply_t *reply, xcb_get_geometry_reply_t *geom);

/**
* Updates the WM_HINTS (we only care about the input focus handling part).
*
Expand Down
4 changes: 2 additions & 2 deletions src/commands.c
Expand Up @@ -467,7 +467,7 @@ static void cmd_resize_floating(I3_CMD, const char *way, const char *direction_s
} else {
floating_con->rect.width += px;
}
floating_check_size(floating_con);
floating_check_size(floating_con, orientation == VERT);

/* Did we actually resize anything or did the size constraints prevent us?
* If we could not resize, exit now to not move the window. */
Expand Down Expand Up @@ -831,7 +831,7 @@ void cmd_append_layout(I3_CMD, const char *cpath) {
// is not executed yet and will be batched with append_layout’s
// needs_tree_render after the parser finished. We should check if that is
// necessary at all.
render_con(croot, false, false);
render_con(croot, false);

restore_open_placeholder_windows(parent);

Expand Down
1 change: 0 additions & 1 deletion src/con.c
Expand Up @@ -46,7 +46,6 @@ Con *con_new_skeleton(Con *parent, i3Window *window) {
new->current_border_width = -1;
if (window) {
new->depth = window->depth;
new->window->aspect_ratio = 0.0;
} else {
new->depth = root_depth;
}
Expand Down
117 changes: 83 additions & 34 deletions src/floating.c
Expand Up @@ -60,12 +60,17 @@ static void floating_set_hint_atom(Con *con, bool floating) {
}

/*
* Called when a floating window is created or resized.
* This function resizes the window if its size is higher or lower than the
* configured maximum/minimum size, respectively.
* Called when a floating window is created or resized. This function resizes
* the window if its size is higher or lower than the configured maximum/minimum
* size, respectively or when adjustments are needed to conform to the
* configured size increments or aspect ratio limits.
*
* When prefer_height is true and the window needs to be resized because of the
* configured aspect ratio, the width is adjusted first, preserving the previous
* height.
*
*/
void floating_check_size(Con *floating_con) {
void floating_check_size(Con *floating_con, bool prefer_height) {
/* Define reasonable minimal and maximal sizes for floating windows */
const int floating_sane_min_height = 50;
const int floating_sane_min_width = 75;
Expand All @@ -83,43 +88,89 @@ void floating_check_size(Con *floating_con) {
border_rect.height += render_deco_height();
}

if (focused_con->window != NULL) {
if (focused_con->window->min_width) {
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, focused_con->window->min_width);
floating_con->rect.width = max(floating_con->rect.width, min_width);
floating_con->rect.width += border_rect.width;
}

if (focused_con->window->min_height) {
if (min_height) {
floating_con->rect.height -= border_rect.height;
floating_con->rect.height = max(floating_con->rect.height, focused_con->window->min_height);
floating_con->rect.height = max(floating_con->rect.height, min_height);
floating_con->rect.height += border_rect.height;
}

if (focused_con->window->max_width) {
if (window->max_width) {
floating_con->rect.width -= border_rect.width;
floating_con->rect.width = min(floating_con->rect.width, focused_con->window->max_width);
floating_con->rect.width = min(floating_con->rect.width, window->max_width);
floating_con->rect.width += border_rect.width;
}

if (focused_con->window->max_height) {
if (window->max_height) {
floating_con->rect.height -= border_rect.height;
floating_con->rect.height = min(floating_con->rect.height, focused_con->window->max_height);
floating_con->rect.height = min(floating_con->rect.height, window->max_height);
floating_con->rect.height += border_rect.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;
/* 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;
}

if (focused_con->window->width_increment &&
floating_con->rect.width >= focused_con->window->base_width + border_rect.width) {
floating_con->rect.width -= focused_con->window->base_width + border_rect.width;
floating_con->rect.width -= floating_con->rect.width % focused_con->window->width_increment;
floating_con->rect.width += focused_con->window->base_width + border_rect.width;
if (window->width_increment &&
floating_con->rect.width >= base_width + border_rect.width) {
floating_con->rect.width -= base_width + border_rect.width;
floating_con->rect.width -= floating_con->rect.width % window->width_increment;
floating_con->rect.width += base_width + border_rect.width;
}
}

Expand Down Expand Up @@ -313,7 +364,7 @@ void floating_enable(Con *con, bool automatic) {
nc->rect.height += con->border_width * 2;
nc->rect.width += con->border_width * 2;

floating_check_size(nc);
floating_check_size(nc, false);

/* Some clients (like GIMP’s color picker window) get mapped
* to (0, 0), so we push them to a reasonable position
Expand Down Expand Up @@ -361,8 +412,7 @@ void floating_enable(Con *con, bool automatic) {
DLOG("Corrected y = %d (deco_height = %d)\n", nc->rect.y, deco_height);

/* render the cons to get initial window_rect correct */
render_con(nc, false, true);
render_con(con, false, true);
render_con(nc, true);

if (set_focus)
con_activate(con);
Expand Down Expand Up @@ -517,7 +567,7 @@ DRAGGING_CB(drag_window_callback) {
con->rect.x = old_rect->x + (new_x - event->root_x);
con->rect.y = old_rect->y + (new_y - event->root_y);

render_con(con, false, true);
render_con(con, true);
x_push_node(con);
xcb_flush(conn);

Expand Down Expand Up @@ -611,7 +661,7 @@ DRAGGING_CB(resize_window_callback) {
con->rect = (Rect){dest_x, dest_y, dest_width, dest_height};

/* Obey window size */
floating_check_size(con);
floating_check_size(con, false);

/* If not the lower right corner is grabbed, we must also reposition
* the client by exactly the amount we resized it */
Expand All @@ -624,9 +674,7 @@ DRAGGING_CB(resize_window_callback) {
con->rect.x = dest_x;
con->rect.y = dest_y;

/* TODO: don’t re-render the whole tree just because we change
* coordinates of a floating window */
tree_render();
render_con(con, true);
x_push_changes(croot);
}

Expand Down Expand Up @@ -907,7 +955,7 @@ bool floating_reposition(Con *con, Rect newrect) {

/* Workspace change will already result in a tree_render. */
if (!reassigned) {
render_con(con, false, true);
render_con(con, true);
x_push_node(con);
}
return true;
Expand All @@ -920,7 +968,7 @@ bool floating_reposition(Con *con, Rect newrect) {
* window's size hints.
*
*/
void floating_resize(Con *floating_con, int x, int y) {
void floating_resize(Con *floating_con, uint32_t x, uint32_t y) {
DLOG("floating resize to %dx%d px\n", x, y);
Rect *rect = &floating_con->rect;
Con *focused_con = con_descend_focused(floating_con);
Expand All @@ -930,14 +978,15 @@ void floating_resize(Con *floating_con, int x, int y) {
}
int wi = focused_con->window->width_increment;
int hi = focused_con->window->height_increment;
bool prefer_height = (rect->width == x);
rect->width = x;
rect->height = y;
if (wi)
rect->width += (wi - 1 - rect->width) % wi;
if (hi)
rect->height += (hi - 1 - rect->height) % hi;

floating_check_size(floating_con);
floating_check_size(floating_con, prefer_height);

/* If this is a scratchpad window, don't auto center it from now on. */
if (floating_con->scratchpad_state == SCRATCHPAD_FRESH)
Expand Down

0 comments on commit bfba56b

Please sign in to comment.