return outputs_dimensions;
}
+/**
+ * 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.
+ *
+ */
+void floating_check_size(Con *floating_con) {
+ /* Define reasonable minimal and maximal sizes for floating windows */
+ const int floating_sane_min_height = 50;
+ const int floating_sane_min_width = 75;
+ Rect floating_sane_max_dimensions;
+ Con *focused_con = con_descend_focused(floating_con);
+
+ /* obey size increments */
+ if (focused_con->height_increment || focused_con->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->height_increment &&
+ floating_con->rect.height >= focused_con->base_height + border_rect.height) {
+ floating_con->rect.height -= focused_con->base_height + border_rect.height;
+ floating_con->rect.height -= floating_con->rect.height % focused_con->height_increment;
+ floating_con->rect.height += focused_con->base_height + border_rect.height;
+ }
+
+ if (focused_con->width_increment &&
+ floating_con->rect.width >= focused_con->base_width + border_rect.width) {
+ floating_con->rect.width -= focused_con->base_width + border_rect.width;
+ floating_con->rect.width -= floating_con->rect.width % focused_con->width_increment;
+ floating_con->rect.width += focused_con->base_width + border_rect.width;
+ }
+ }
+
+ /* Unless user requests otherwise (-1), ensure width/height do not exceed
+ * configured maxima or, if unconfigured, limit to combined width of all
+ * outputs */
+ if (config.floating_minimum_height != -1) {
+ if (config.floating_minimum_height == 0)
+ floating_con->rect.height = max(floating_con->rect.height, floating_sane_min_height);
+ else
+ floating_con->rect.height = max(floating_con->rect.height, config.floating_minimum_height);
+ }
+ if (config.floating_minimum_width != -1) {
+ if (config.floating_minimum_width == 0)
+ floating_con->rect.width = max(floating_con->rect.width, floating_sane_min_width);
+ else
+ floating_con->rect.width = max(floating_con->rect.width, config.floating_minimum_width);
+ }
+
+ /* Unless user requests otherwise (-1), raise the width/height to
+ * reasonable minimum dimensions */
+ floating_sane_max_dimensions = total_outputs_dimensions();
+ if (config.floating_maximum_height != -1) {
+ if (config.floating_maximum_height == 0)
+ floating_con->rect.height = min(floating_con->rect.height, floating_sane_max_dimensions.height);
+ else
+ floating_con->rect.height = min(floating_con->rect.height, config.floating_maximum_height);
+ }
+ if (config.floating_maximum_width != -1) {
+ if (config.floating_maximum_width == 0)
+ floating_con->rect.width = min(floating_con->rect.width, floating_sane_max_dimensions.width);
+ else
+ floating_con->rect.width = min(floating_con->rect.width, config.floating_maximum_width);
+ }
+}
+
void floating_enable(Con *con, bool automatic) {
bool set_focus = (con == focused);
free(name);
/* find the height for the decorations */
- int deco_height = config.font.height + 5;
+ int deco_height = render_deco_height();
DLOG("Original rect: (%d, %d) with %d x %d\n", con->rect.x, con->rect.y, con->rect.width, con->rect.height);
DLOG("Geometry = (%d, %d) with %d x %d\n", con->geometry.x, con->geometry.y, con->geometry.width, con->geometry.height);
}
}
- /* Define reasonable minimal and maximal sizes for floating windows */
- const int floating_sane_min_height = 50;
- const int floating_sane_min_width = 75;
-
- Rect floating_sane_max_dimensions;
- floating_sane_max_dimensions = total_outputs_dimensions();
-
- /* Unless user requests otherwise (-1), ensure width/height do not exceed
- * configured maxima or, if unconfigured, limit to combined width of all
- * outputs */
- if (config.floating_maximum_height != -1) {
- if (config.floating_maximum_height == 0)
- nc->rect.height = min(nc->rect.height, floating_sane_max_dimensions.height);
- else
- nc->rect.height = min(nc->rect.height, config.floating_maximum_height);
- }
- if (config.floating_maximum_width != -1) {
- if (config.floating_maximum_width == 0)
- nc->rect.width = min(nc->rect.width, floating_sane_max_dimensions.width);
- else
- nc->rect.width = min(nc->rect.width, config.floating_maximum_width);
- }
-
- /* Unless user requests otherwise (-1), raise the width/height to
- * reasonable minimum dimensions */
- if (config.floating_minimum_height != -1) {
- if (config.floating_minimum_height == 0)
- nc->rect.height = max(nc->rect.height, floating_sane_min_height);
- else
- nc->rect.height = max(nc->rect.height, config.floating_minimum_height);
- }
- if (config.floating_minimum_width != -1) {
- if (config.floating_minimum_width == 0)
- nc->rect.width = max(nc->rect.width, floating_sane_min_width);
- else
- nc->rect.width = max(nc->rect.width, config.floating_minimum_width);
- }
+ floating_check_size(nc);
/* 3: attach the child to the new parent container. We need to do this
* because con_border_style_rect() needs to access con->parent. */
/* 5: Subtract the deco_height in order to make the floating window appear
* at precisely the position it specified in its original geometry (which
* is what applications might remember). */
- deco_height = (con->border_style == BS_NORMAL ? config.font.height + 5 : 0);
+ deco_height = (con->border_style == BS_NORMAL ? render_deco_height() : 0);
nc->rect.y -= deco_height;
DLOG("Corrected y = %d (deco_height = %d)\n", nc->rect.y, deco_height);
return;
}
+ const bool set_focus = (con == focused);
+
Con *ws = con_get_workspace(con);
/* 1: detach from parent container */
con_attach(con, con->parent, false);
con_fix_percent(con->parent);
- // TODO: don’t influence focus handling when Con was not focused before.
- con_focus(con);
+
+ if (set_focus)
+ con_focus(con);
}
/*
/* Check if we cross workspace boundaries while moving */
if (!floating_maybe_reassign_ws(con))
return;
+ /* Ensure not to warp the pointer while dragging */
+ x_set_warp_to(NULL);
tree_render();
}
/* Drag the window */
drag_pointer(con, event, XCB_NONE, BORDER_TOP /* irrelevant */, XCURSOR_CURSOR_MOVE, drag_window_callback, event);
+
+ /* If this is a scratchpad window, don't auto center it from now on. */
+ if (con->scratchpad_state == SCRATCHPAD_FRESH)
+ con->scratchpad_state = SCRATCHPAD_CHANGED;
+
tree_render();
}
dest_height = old_rect->height - (new_y - event->root_y);
else dest_height = old_rect->height + (new_y - event->root_y);
- /* Obey minimum window size */
- Rect minimum = con_minimum_size(con);
- dest_width = max(dest_width, minimum.width);
- dest_height = max(dest_height, minimum.height);
-
/* User wants to keep proportions, so we may have to adjust our values */
if (params->proportional) {
dest_width = max(dest_width, (int) (dest_height * ratio));
dest_height = max(dest_height, (int) (dest_width / ratio));
}
+ con->rect = (Rect) { dest_x, dest_y, dest_width, dest_height };
+
+ /* Obey window size */
+ floating_check_size(con);
+
/* If not the lower right corner is grabbed, we must also reposition
* the client by exactly the amount we resized it */
if (corner & BORDER_LEFT)
- dest_x = old_rect->x + (old_rect->width - dest_width);
+ dest_x = old_rect->x + (old_rect->width - con->rect.width);
if (corner & BORDER_TOP)
- dest_y = old_rect->y + (old_rect->height - dest_height);
+ dest_y = old_rect->y + (old_rect->height - con->rect.height);
- con->rect = (Rect) { dest_x, dest_y, dest_width, dest_height };
+ 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 */
struct resize_window_callback_params params = { corner, proportional, event };
drag_pointer(con, event, XCB_NONE, BORDER_TOP /* irrelevant */, cursor, resize_window_callback, ¶ms);
+
+ /* If this is a scratchpad window, don't auto center it from now on. */
+ if (con->scratchpad_state == SCRATCHPAD_FRESH)
+ con->scratchpad_state = SCRATCHPAD_CHANGED;
}
/*
void floating_reposition(Con *con, Rect newrect) {
/* Sanity check: Are the new coordinates on any output? If not, we
* ignore that request. */
- Output *output = get_output_containing(
- newrect.x + (newrect.width / 2),
- newrect.y + (newrect.height / 2));
-
- if (!output) {
+ if (!contained_by_output(newrect)) {
ELOG("No output found at destination coordinates. Not repositioning.\n");
return;
}
con->rect = newrect;
floating_maybe_reassign_ws(con);
+
+ /* If this is a scratchpad window, don't auto center it from now on. */
+ if (con->scratchpad_state == SCRATCHPAD_FRESH)
+ con->scratchpad_state = SCRATCHPAD_CHANGED;
+
tree_render();
}