44        place(c, area, policy);
 
   53        placeOnMainWindow(c, area.toRect()); 
 
   55        placeOnScreenDisplay(c, area.toRect());
 
 
   75        placeAtRandom(c, area.toRect(), nextPlacement);
 
   81        placeZeroCornered(c, area.toRect(), nextPlacement);
 
   84        placeUnderMouse(c, area.toRect(), nextPlacement);
 
   87        placeOnMainWindow(c, area.toRect(), nextPlacement);
 
   90        placeMaximizing(c, area.toRect(), nextPlacement);
 
  102    Q_ASSERT(area.isValid());
 
  105    static int px = step;
 
  106    static int py = 2 * step;
 
  119    if (px > area.width() / 2) {
 
  120        px = area.x() + step;
 
  122    if (py > area.height() / 2) {
 
  123        py = area.y() + step;
 
  127    if (tx + c->width() > area.right()) {
 
  128        tx = area.right() - c->width();
 
  134    if (ty + c->height() > area.bottom()) {
 
  135        ty = area.bottom() - c->height();
 
  141    c->move(QPoint(tx, ty));
 
  145static inline bool isIrrelevant(
const Window *window, 
const Window *regarding, VirtualDesktop *desktop)
 
  147    return window == regarding
 
  148        || !window->isClient()
 
  149        || !window->isShown()
 
  151        || !window->isOnDesktop(desktop)
 
  152        || !window->isOnCurrentActivity()
 
  153        || window->isDesktop();
 
  161    Q_ASSERT(area.isValid());
 
  176    const int none = 0, h_wrong = -1, w_wrong = -2; 
 
  177    long int overlap, min_overlap = 0;
 
  178    int x_optimal, y_optimal;
 
  182    int cxl, cxr, cyt, cyb; 
 
  193    int ch = std::ceil(window->
height());
 
  194    int cw = std::ceil(window->
width());
 
  198    int area_xr = std::floor(area.x() + area.width());
 
  199    int area_yb = std::floor(area.y() + area.height());
 
  201    bool first_pass = 
true; 
 
  206        if (y + ch > area_yb && ch < area.height()) {
 
  208        } 
else if (x + cw > area_xr) {
 
  219                if (isIrrelevant(client, window, desktop)) {
 
  224                xr = xl + client->width();
 
  225                yb = yt + client->height();
 
  228                if ((cxl < xr) && (cxr > xl) && (cyt < yb) && (cyb > yt)) {
 
  229                    xl = std::max(cxl, xl);
 
  230                    xr = std::min(cxr, xr);
 
  231                    yt = std::max(cyt, yt);
 
  232                    yb = std::min(cyb, yb);
 
  233                    if (client->keepAbove()) {
 
  234                        overlap += 16 * (xr - xl) * (yb - yt);
 
  235                    } 
else if (client->keepBelow() && !client->isDock()) { 
 
  238                        overlap += (xr - xl) * (yb - yt);
 
  245        if (overlap == none) {
 
  253            min_overlap = overlap;
 
  256        else if (overlap >= none && overlap < min_overlap) {
 
  257            min_overlap = overlap;
 
  263        if (overlap > none) {
 
  266            if (possible - cw > x) {
 
  273                if (isIrrelevant(client, window, desktop)) {
 
  279                xr = xl + client->width();
 
  280                yb = yt + client->height();
 
  284                if ((y < yb) && (yt < ch + y)) {
 
  286                    if ((xr > x) && (possible > xr)) {
 
  291                    if ((basket > x) && (possible > basket)) {
 
  300        else if (overlap == w_wrong) {
 
  304            if (possible - ch > y) {
 
  311                if (isIrrelevant(client, window, desktop)) {
 
  317                xr = xl + client->width();
 
  318                yb = yt + client->height();
 
  322                if ((yb > y) && (possible > yb)) {
 
  327                if ((basket > y) && (possible > basket)) {
 
  333    } 
while ((overlap != none) && (overlap != h_wrong) && (y < area_yb));
 
  335    if (ch >= area.height()) {
 
  336        y_optimal = area.top();
 
  340    window->
move(QPoint(x_optimal, y_optimal));
 
 
  346    const auto desktops = VirtualDesktopManager::self()->desktops();
 
 
  354    cci[desktop] = DesktopCascadingInfo{
 
  355        .pos = QPoint(-1, -1),
 
 
  364    return QPoint(area.width() / 48, area.height() / 48);
 
 
  372    Q_ASSERT(area.isValid());
 
  388    if (cci[dn].pos.x() < 0 || cci[dn].pos.x() < area.left() || cci[dn].pos.y() < area.top()) {
 
  389        cci[dn].pos = QPoint(area.left(), area.top());
 
  390        cci[dn].col = cci[dn].row = 0;
 
  393    int xp = cci[dn].pos.x();
 
  394    int yp = cci[dn].pos.y();
 
  397    if ((yp + c->
height()) > area.height()) {
 
  401    if ((xp + c->
width()) > area.width()) {
 
  403            place(c, area, nextPlacement);
 
  411    if (cci[dn].pos.x() != area.left() && cci[dn].pos.y() != area.top()) {
 
  412        if (xp != area.left() && yp == area.top()) {
 
  414            xp = delta.x() * cci[dn].col;
 
  416        if (yp != area.top() && xp == area.left()) {
 
  418            yp = delta.y() * cci[dn].row;
 
  422        if (((xp + c->
width()) > area.width() - area.left()) || ((yp + c->
height()) > area.height() - area.top())) {
 
  423            place(c, area, nextPlacement);
 
  429    c->
move(QPoint(xp, yp));
 
  432    cci[dn].pos = QPoint(xp + delta.x(), yp + delta.y());
 
  440    Q_ASSERT(area.isValid());
 
  446    const int xp = area.left() + (area.width() - c->
width()) / 2;
 
  447    const int yp = area.top() + (area.height() - c->
height()) / 2;
 
  450    c->
move(QPoint(xp, yp));
 
 
  459    Q_ASSERT(area.isValid());
 
  462    c->
move(area.topLeft());
 
  476void Placement::placeOnScreenDisplay(
Window *c, 
const QRect &area)
 
  478    Q_ASSERT(area.isValid());
 
  481    const int x = area.left() + (area.width() - c->width()) / 2;
 
  482    const int y = area.top() + 2 * area.height() / 3 - c->height() / 2;
 
  484    c->move(QPoint(x, y));
 
  487void Placement::placeTransient(
Window *c)
 
  489    c->moveResize(c->transientPlacement());
 
  494    placeOnMainWindow(c, area, nextPlacement);
 
  499    Q_ASSERT(area.isValid());
 
  501    QRectF geom = c->frameGeometry();
 
  503    c->move(geom.topLeft().toPoint());
 
  510    Q_ASSERT(area.isValid());
 
  518    auto mainwindows = c->mainWindows();
 
  519    Window *place_on = 
nullptr;
 
  520    Window *place_on2 = 
nullptr;
 
  522    for (
auto it = mainwindows.constBegin(); it != mainwindows.constEnd(); ++it) {
 
  523        if (mainwindows.count() > 1 && (*it)->isSpecialWindow()) {
 
  528        if ((*it)->isOnCurrentDesktop()) {
 
  529            if (place_on == 
nullptr) {
 
  543    if (place_on == 
nullptr) {
 
  545        if (mains_count != 1) {
 
  549        place_on = place_on2; 
 
  551    if (place_on->isDesktop()) {
 
  555    QRect geom = c->frameGeometry().toRect();
 
  556    geom.moveCenter(place_on->frameGeometry().center().toPoint());
 
  557    c->move(geom.topLeft());
 
  560    c->keepInArea(placementArea); 
 
  565    Q_ASSERT(area.isValid());
 
  570    if (c->isMaximizable() && c->maxSize().width() >= area.width() && c->maxSize().height() >= area.height()) {
 
  578        c->moveResize(c->resizeWithChecks(c->moveResizeGeometry(), c->maxSize().boundedTo(area.size())));
 
  579        place(c, area, nextPlacement);
 
  593    bool noOverlap = 
false;
 
  602            if (isIrrelevant(other, window, desktop) || !other->frameGeometry().intersects(possibleGeo)) {
 
  606            if (possibleGeo.contains(other->frameGeometry()) && !coveredArea.contains(other->frameGeometry())) {
 
  611                possibleGeo.moveTopLeft(other->pos() + offset);
 
  612                if (possibleGeo.right() > area.right() || possibleGeo.bottom() > area.bottom()) {
 
  623            coveredArea |= other->frameGeometry();
 
  624            if (coveredArea.contains(area)) {
 
  630    window->
move(possibleGeo.topLeft());
 
 
  638    for (
Window *window : stackingOrder) {
 
  639        if (!window->isClient() || (!window->isOnCurrentDesktop()) || (window->isMinimized()) || (window->isOnAllDesktops()) || (!window->isMovable())) {
 
  643        placeCascaded(window, placementArea);
 
 
  650    for (
int i = windows.size() - 1; i >= 0; i--) {
 
  651        auto window = windows.at(i);
 
  652        if (!window->isClient()) {
 
  655        if ((!window->isOnCurrentDesktop()) || (window->isMinimized()) || (window->isOnAllDesktops()) || (!window->isMovable())) {
 
 
  667    const char *
const policies[] = {
 
  668        "NoPlacement", 
"Default", 
"XXX should never see", 
"Random", 
"Smart", 
"Centered",
 
  669        "ZeroCornered", 
"UnderMouse", 
"OnMainWindow", 
"Maximizing"};
 
  670    Q_ASSERT(policy < 
int(
sizeof(policies) / 
sizeof(policies[0])));
 
  671    return policies[policy];
 
 
  685    move(QPoint(left, top));
 
 
  699    if (m_activeWindow && m_activeWindow->
isMovable()) {
 
 
  708    if (m_activeWindow && m_activeWindow->
isMovable()) {
 
 
  717    if (m_activeWindow && m_activeWindow->
isMovable()) {
 
 
  726    if (m_activeWindow && m_activeWindow->
isMovable()) {
 
 
  736    if (m_activeWindow && m_activeWindow->
isMovable()) {
 
  740                               center.y() - (
geometry.height() / 2));
 
 
  746    if (m_activeWindow) {
 
 
  757    geom.setRight(
workspace()->packPositionRight(
this, geom.right(), 
true));
 
  768            geom.setRight(newright);
 
 
  779    if (m_activeWindow) {
 
 
  790    geom.setRight(
workspace()->packPositionLeft(
this, geom.right(), 
false) + 1);
 
  791    if (geom.width() <= 1) {
 
  795    if (geom.width() > 20) {
 
 
  803    if (m_activeWindow) {
 
 
  814    geom.setBottom(
workspace()->packPositionDown(
this, geom.bottom(), 
true));
 
  824            geom.setBottom(newbottom);
 
 
  834    if (m_activeWindow) {
 
 
  845    geom.setBottom(
workspace()->packPositionUp(
this, geom.bottom(), 
false) + 1);
 
  846    if (geom.height() <= 1) {
 
  850    if (geom.height() > 20) {
 
 
  858    if (!m_activeWindow) {
 
  864#define FLAG(name) QuickTileMode(QuickTileFlag::name) 
  865    if (!m_quickTileCombineTimer->isActive()) {
 
  866        m_quickTileCombineTimer->start(1000);
 
  867        m_lastTilingMode = mode;
 
  874            mode |= m_lastTilingMode;
 
  876        m_quickTileCombineTimer->stop();
 
 
  895    for (
auto it = m_windows.constBegin(), end = m_windows.constEnd(); it != end; ++it) {
 
  896        if (isIrrelevant(*it, window, desktop)) {
 
  899        const qreal x = leftEdge ? (*it)->frameGeometry().right() : (*it)->frameGeometry().left() - 1;
 
  900        if (x > newX && x < oldX
 
  901            && !(window->
frameGeometry().top() > (*it)->frameGeometry().bottom() - 1 
 
  902                 || window->
frameGeometry().bottom() - 1 < (*it)->frameGeometry().top())) {
 
 
  922    for (
auto it = m_windows.constBegin(), end = m_windows.constEnd(); it != end; ++it) {
 
  923        if (isIrrelevant(*it, window, desktop)) {
 
  926        const qreal x = rightEdge ? (*it)->frameGeometry().left() : (*it)->frameGeometry().right() + 1;
 
  928        if (x < newX && x > oldX
 
  929            && !(window->
frameGeometry().top() > (*it)->frameGeometry().bottom() - 1
 
  930                 || window->
frameGeometry().bottom() - 1 < (*it)->frameGeometry().top())) {
 
 
  950    for (
auto it = m_windows.constBegin(), end = m_windows.constEnd(); it != end; ++it) {
 
  951        if (isIrrelevant(*it, window, desktop)) {
 
  954        const qreal y = topEdge ? (*it)->frameGeometry().bottom() : (*it)->frameGeometry().top() - 1;
 
  955        if (y > newY && y < oldY
 
  956            && !(window->
frameGeometry().left() > (*it)->frameGeometry().right() - 1 
 
  957                 || window->
frameGeometry().right() - 1 < (*it)->frameGeometry().left())) {
 
 
  977    for (
auto it = m_windows.constBegin(), end = m_windows.constEnd(); it != end; ++it) {
 
  978        if (isIrrelevant(*it, window, desktop)) {
 
  981        const qreal y = bottomEdge ? (*it)->frameGeometry().top() : (*it)->frameGeometry().bottom() + 1;
 
  982        if (y < newY && y > oldY
 
  983            && !(window->
frameGeometry().left() > (*it)->frameGeometry().right() - 1
 
  984                 || window->
frameGeometry().right() - 1 < (*it)->frameGeometry().left())) {
 
 
PlacementPolicy placement
void placeCentered(Window *c, const QRectF &area, PlacementPolicy next=PlacementUnknown)
static const char * policyToString(PlacementPolicy policy)
void placeSmart(Window *c, const QRectF &area, PlacementPolicy next=PlacementUnknown)
void place(Window *c, const QRectF &area)
void cascadeIfCovering(Window *c, const QRectF &area)
virtual bool hasTransientPlacementHint() const
void moveResize(const QRectF &rect)
virtual bool isTransient() const
bool isNotification() const
SurfaceInterface * surface() const
bool isOnScreenDisplay() const
bool isCriticalNotification() const
void packTo(qreal left, qreal top)
virtual QSizeF resizeIncrements() const
void setQuickTileMode(QuickTileMode mode, bool keyboard=false)
bool isOnCurrentDesktop() const
virtual MaximizeMode requestedMaximizeMode() const
QList< KWin::VirtualDesktop * > desktops
virtual bool isMovable() const =0
@ SizeModeFixedW
Try not to affect width.
@ SizeModeFixedH
Try not to affect height.
Output * moveResizeOutput() const
QRectF moveResizeGeometry() const
const WindowRules * rules() const
QSizeF constrainFrameSize(const QSizeF &size, SizeMode mode=SizeModeAny) const
void checkWorkspacePosition(QRectF oldGeometry=QRectF(), const VirtualDesktop *oldDesktop=nullptr)
virtual bool isResizable() const =0
PlacementPolicy checkPlacement(PlacementPolicy placement) const
void quickTileWindow(QuickTileMode mode)
QRectF clientArea(clientAreaOption, const Output *output, const VirtualDesktop *desktop) const
const QList< Window * > & stackingOrder() const
void sendWindowToOutput(Window *window, Output *output)
qreal packPositionDown(const Window *window, qreal oldY, bool bottomEdge) const
void slotWindowShrinkHorizontal()
void slotWindowExpandHorizontal()
static Workspace * self()
void slotWindowMoveDown()
void updateFocusMousePosition(const QPointF &pos)
QPoint cascadeOffset(const Window *c) const
void slotWindowMoveRight()
void slotWindowShrinkVertical()
const QList< Window * > windows() const
qreal packPositionRight(const Window *window, qreal oldX, bool rightEdge) const
void slotWindowExpandVertical()
qreal packPositionUp(const Window *window, qreal oldY, bool topEdge) const
qreal packPositionLeft(const Window *window, qreal oldX, bool leftEdge) const
void slotWindowMoveLeft()
@ MaximizeRestore
The window is not maximized in any direction.
@ MaximizeFull
Equal to MaximizeVertical | MaximizeHorizontal.