* Find a good place for opening a new window of a given width and height. * @param width Width of the new window * @param height Height of the new window * @return Top-left coordinate of the new window */
| 1615 | * @return Top-left coordinate of the new window |
| 1616 | */ |
| 1617 | static Point GetAutoPlacePosition(int width, int height) |
| 1618 | { |
| 1619 | Point pt; |
| 1620 | |
| 1621 | bool rtl = _current_text_dir == TD_RTL; |
| 1622 | |
| 1623 | /* First attempt, try top-left of the screen */ |
| 1624 | const Window *main_toolbar = FindWindowByClass(WC_MAIN_TOOLBAR); |
| 1625 | const int toolbar_y = main_toolbar != nullptr ? main_toolbar->height : 0; |
| 1626 | if (IsGoodAutoPlace1(rtl ? _screen.width - width : 0, toolbar_y, width, height, toolbar_y, pt)) return pt; |
| 1627 | |
| 1628 | /* Second attempt, try around all existing windows. |
| 1629 | * The new window must be entirely on-screen, and not overlap with an existing window. |
| 1630 | * Eight starting points are tried, two at each corner. |
| 1631 | */ |
| 1632 | for (const Window *w : Window::Iterate()) { |
| 1633 | if (w->window_class == WC_MAIN_WINDOW) continue; |
| 1634 | |
| 1635 | if (IsGoodAutoPlace1(w->left + w->width, w->top, width, height, toolbar_y, pt)) return pt; |
| 1636 | if (IsGoodAutoPlace1(w->left - width, w->top, width, height, toolbar_y, pt)) return pt; |
| 1637 | if (IsGoodAutoPlace1(w->left, w->top + w->height, width, height, toolbar_y, pt)) return pt; |
| 1638 | if (IsGoodAutoPlace1(w->left, w->top - height, width, height, toolbar_y, pt)) return pt; |
| 1639 | if (IsGoodAutoPlace1(w->left + w->width, w->top + w->height - height, width, height, toolbar_y, pt)) return pt; |
| 1640 | if (IsGoodAutoPlace1(w->left - width, w->top + w->height - height, width, height, toolbar_y, pt)) return pt; |
| 1641 | if (IsGoodAutoPlace1(w->left + w->width - width, w->top + w->height, width, height, toolbar_y, pt)) return pt; |
| 1642 | if (IsGoodAutoPlace1(w->left + w->width - width, w->top - height, width, height, toolbar_y, pt)) return pt; |
| 1643 | } |
| 1644 | |
| 1645 | /* Third attempt, try around all existing windows. |
| 1646 | * The new window may be partly off-screen, and must not overlap with an existing window. |
| 1647 | * Only four starting points are tried. |
| 1648 | */ |
| 1649 | for (const Window *w : Window::Iterate()) { |
| 1650 | if (w->window_class == WC_MAIN_WINDOW) continue; |
| 1651 | |
| 1652 | if (IsGoodAutoPlace2(w->left + w->width, w->top, width, height, toolbar_y, pt)) return pt; |
| 1653 | if (IsGoodAutoPlace2(w->left - width, w->top, width, height, toolbar_y, pt)) return pt; |
| 1654 | if (IsGoodAutoPlace2(w->left, w->top + w->height, width, height, toolbar_y, pt)) return pt; |
| 1655 | if (IsGoodAutoPlace2(w->left, w->top - height, width, height, toolbar_y, pt)) return pt; |
| 1656 | } |
| 1657 | |
| 1658 | /* Fourth and final attempt, put window at diagonal starting from (0, toolbar_y), try multiples |
| 1659 | * of the closebox |
| 1660 | */ |
| 1661 | int left = rtl ? _screen.width - width : 0, top = toolbar_y; |
| 1662 | int offset_x = rtl ? -(int)NWidgetLeaf::closebox_dimension.width : (int)NWidgetLeaf::closebox_dimension.width; |
| 1663 | int offset_y = std::max<int>(NWidgetLeaf::closebox_dimension.height, GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.captiontext.Vertical()); |
| 1664 | |
| 1665 | restart: |
| 1666 | for (const Window *w : Window::Iterate()) { |
| 1667 | if (w->left == left && w->top == top) { |
| 1668 | left += offset_x; |
| 1669 | top += offset_y; |
| 1670 | goto restart; |
| 1671 | } |
| 1672 | } |
| 1673 | |
| 1674 | pt.x = left; |
no test coverage detected