*/
Output *get_output_containing(unsigned int x, unsigned int y);
+/**
+ * Returns the active output which contains the midpoint of the given rect. If
+ * such an output doesn't exist, returns the output which contains most of the
+ * rectangle or NULL if there is no output which intersects with it.
+ *
+ */
+Output *get_output_from_rect(Rect rect);
+
/**
* Returns the active output which spans exactly the area specified by
* rect or NULL if there is no output like this.
*/
Output *get_output_with_dimensions(Rect rect);
-/*
- * In contained_by_output, we check if any active output contains part of the container.
+/**
+ * In output_containing_rect, we check if any active output contains part of the container.
* We do this by checking if the output rect is intersected by the Rect.
* This is the 2-dimensional counterpart of get_output_containing.
- * Since we don't actually need the outputs intersected by the given Rect (There could
- * be many), we just return true or false for convenience.
+ * Returns the output with the maximum intersecting area.
*
*/
-bool contained_by_output(Rect rect);
+Output *output_containing_rect(Rect rect);
/**
* Gets the output which is the next one in the given direction.
/* Sanity check: Are the coordinates on the appropriate output? If not, we
* need to change them */
- Output *current_output = get_output_containing(nc->rect.x +
- (nc->rect.width / 2),
- nc->rect.y + (nc->rect.height / 2));
-
+ Output *current_output = get_output_from_rect(nc->rect);
Con *correct_output = con_get_output(ws);
if (!current_output || current_output->con != correct_output) {
DLOG("This floating window is on the wrong output, fixing coordinates (currently (%d, %d))\n",
/* If moving from one output to another, keep the relative position
* consistent (e.g. a centered dialog will remain centered). */
- if (current_output)
+ if (current_output) {
floating_fix_coordinates(nc, ¤t_output->con->rect, &correct_output->rect);
- else {
- nc->rect.x = correct_output->rect.x;
- nc->rect.y = correct_output->rect.y;
+ /* Make sure that the result is in the correct output. */
+ current_output = get_output_from_rect(nc->rect);
+ }
+ if (!current_output || current_output->con != correct_output) {
+ floating_center(nc, ws->rect);
}
}
if (set_focus)
con_activate(con);
- /* Check if we need to re-assign it to a different workspace because of its
- * coordinates and exit if that was done successfully. */
- if (floating_maybe_reassign_ws(nc)) {
- goto done;
- }
-
- /* Sanitize coordinates: Check if they are on any output */
- if (get_output_containing(nc->rect.x, nc->rect.y) != NULL) {
- goto done;
- }
-
- ELOG("No output found at destination coordinates, centering floating window on current ws\n");
- floating_center(nc, ws->rect);
-
-done:
floating_set_hint_atom(nc, true);
ipc_send_window_event("floating", con);
}
*
*/
bool floating_maybe_reassign_ws(Con *con) {
- Output *output = get_output_containing(
- con->rect.x + (con->rect.width / 2),
- con->rect.y + (con->rect.height / 2));
+ Output *output = get_output_from_rect(con->rect);
if (!output) {
ELOG("No output found at destination coordinates?\n");
bool floating_reposition(Con *con, Rect newrect) {
/* Sanity check: Are the new coordinates on any output? If not, we
* ignore that request. */
- if (!contained_by_output(newrect)) {
+ if (!output_containing_rect(newrect)) {
ELOG("No output found at destination coordinates. Not repositioning.\n");
return false;
}
return NULL;
}
+/*
+ * Returns the active output which contains the midpoint of the given rect. If
+ * such an output doesn't exist, returns the output which contains most of the
+ * rectangle or NULL if there is no output which intersects with it.
+ *
+ */
+Output *get_output_from_rect(Rect rect) {
+ unsigned int mid_x = rect.x + rect.width / 2;
+ unsigned int mid_y = rect.y + rect.height / 2;
+ Output *output = get_output_containing(mid_x, mid_y);
+
+ return output ? output : output_containing_rect(rect);
+}
+
/*
* Returns the active output which spans exactly the area specified by
* rect or NULL if there is no output like this.
}
/*
- * In contained_by_output, we check if any active output contains part of the container.
+ * In output_containing_rect, we check if any active output contains part of the container.
* We do this by checking if the output rect is intersected by the Rect.
* This is the 2-dimensional counterpart of get_output_containing.
- * Since we don't actually need the outputs intersected by the given Rect (There could
- * be many), we just return true or false for convenience.
+ * Returns the output with the maximum intersecting area.
*
*/
-bool contained_by_output(Rect rect) {
+Output *output_containing_rect(Rect rect) {
Output *output;
int lx = rect.x, uy = rect.y;
int rx = rect.x + rect.width, by = rect.y + rect.height;
+ long max_area = 0;
+ Output *result = NULL;
TAILQ_FOREACH(output, &outputs, outputs) {
if (!output->active)
continue;
+ int lx_o = (int)output->rect.x, uy_o = (int)output->rect.y;
+ int rx_o = (int)(output->rect.x + output->rect.width), by_o = (int)(output->rect.y + output->rect.height);
DLOG("comparing x=%d y=%d with x=%d and y=%d width %d height %d\n",
rect.x, rect.y, output->rect.x, output->rect.y, output->rect.width, output->rect.height);
- if (rx >= (int)output->rect.x && lx <= (int)(output->rect.x + output->rect.width) &&
- by >= (int)output->rect.y && uy <= (int)(output->rect.y + output->rect.height))
- return true;
+ int left = max(lx, lx_o);
+ int right = min(rx, rx_o);
+ int bottom = min(by, by_o);
+ int top = max(uy, uy_o);
+ if (left < right && bottom > top) {
+ long area = (right - left) * (bottom - top);
+ if (area > max_area) {
+ result = output;
+ }
+ }
}
- return false;
+ return result;
}
/*