~alan-griffiths/qtmir/mir-0.27-compat-artful

« back to all changes in this revision

Viewing changes to src/platforms/mirserver/windowmanagementpolicy.cpp

  • Committer: Bileto Bot
  • Author(s): Gerry Boland
  • Date: 2017-03-28 17:12:22 UTC
  • mfrom: (618.4.16 availableDesktopArea)
  • Revision ID: ci-train-bot@canonical.com-20170328171222-oe9veuhwgimi0qq7
Don't let a child window go offscreen because its parent moved

Approved by: Daniel d'Andrada, Unity8 CI Bot

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
#include "mirqtconversion.h"
28
28
#include "tracepoints.h"
29
29
 
30
 
#include <QDebug>
31
 
 
32
30
namespace qtmir {
33
31
    std::shared_ptr<ExtraWindowInfo> getExtraInfo(const miral::WindowInfo &windowInfo) {
34
32
        return std::static_pointer_cast<ExtraWindowInfo>(windowInfo.userdata());
36
34
}
37
35
 
38
36
using namespace qtmir;
39
 
using namespace mir::geometry;
40
37
 
41
38
WindowManagementPolicy::WindowManagementPolicy(const miral::WindowManagerTools &tools,
42
39
                                               qtmir::WindowModelNotifier &windowModel,
69
66
        QSize initialSize = InitialSurfaceSizes::get(miral::pid_of(appInfo.application()));
70
67
 
71
68
        if (initialSize.isValid() && surfaceType == mir_surface_type_normal) {
72
 
            parameters.size() = Size{Width(initialSize.width()), Height(initialSize.height())};
 
69
            parameters.size() = toMirSize(initialSize);
73
70
        }
74
71
    }
75
72
 
227
224
    });
228
225
}
229
226
 
 
227
QRect WindowManagementPolicy::getConfinementRect(const QRect rect) const
 
228
{
 
229
    QRect confinementRect;
 
230
    for (const QRect r : m_confinementRegions) {
 
231
        if (r.intersects(rect)) {
 
232
            confinementRect = r;
 
233
            // TODO: What if there are multiple confinement regions and they intersect??
 
234
            break;
 
235
        }
 
236
    }
 
237
    return confinementRect;
 
238
}
 
239
 
230
240
/* Following methods all called from the Qt GUI thread to deliver events to clients */
231
241
void WindowManagementPolicy::deliver_keyboard_event(const MirKeyboardEvent *event,
232
242
                                                    const miral::Window &window)
330
340
    });
331
341
}
332
342
 
 
343
void WindowManagementPolicy::set_window_confinement_regions(const QVector<QRect> &regions)
 
344
{
 
345
    m_confinementRegions = regions;
 
346
 
 
347
    // TODO: update window positions to respect new boundary.
 
348
}
 
349
 
 
350
void WindowManagementPolicy::set_window_margins(MirWindowType windowType, const QMargins &margins)
 
351
{
 
352
    m_windowMargins[windowType] = margins;
 
353
 
 
354
    // TODO: update window positions/sizes to respect new margins.
 
355
}
 
356
 
333
357
void WindowManagementPolicy::requestState(const miral::Window &window, const Mir::State state)
334
358
{
335
359
    auto &windowInfo = m_tools.info_for(window);
354
378
        });
355
379
    }
356
380
}
 
381
 
 
382
Rectangle WindowManagementPolicy::confirm_inherited_move(miral::WindowInfo const& windowInfo, Displacement movement)
 
383
{
 
384
    if (m_confinementRegions.isEmpty()) {
 
385
        return CanonicalWindowManagerPolicy::confirm_inherited_move(windowInfo, movement);
 
386
    }
 
387
 
 
388
    auto window = windowInfo.window();
 
389
    const QMargins windowMargins = m_windowMargins[windowInfo.type()];
 
390
    QRect windowGeom(toQPoint(window.top_left()), toQSize(window.size()));
 
391
 
 
392
    QRect geom = windowGeom.marginsAdded(windowMargins);
 
393
    const QRect confinementRect = getConfinementRect(geom);
 
394
 
 
395
    int x = geom.x();
 
396
    int y = geom.y();
 
397
    int moveX = movement.dx.as_int();
 
398
    int moveY = movement.dy.as_int();
 
399
 
 
400
    // If the child window is already partially beyond the available desktop area (most likely because the user
 
401
    // explicitly moved it there) we won't pull it back, unless the inherited movement is this direction, but also won't
 
402
    // push it even further astray. But if it currently is completely within the available desktop area boundaries
 
403
    // we won't let go beyond it.
 
404
 
 
405
    if (moveX > 0) {
 
406
        if (geom.right() < confinementRect.right()) {
 
407
            x = qMin(x + moveX, confinementRect.right() + 1 - geom.width()); // +1 because QRect::right() weird
 
408
        }
 
409
    } else {
 
410
        if (geom.x() > confinementRect.left()) {
 
411
            x = qMax(x + moveX, confinementRect.left());
 
412
        }
 
413
    }
 
414
 
 
415
    if (moveY > 0) {
 
416
        if (geom.bottom() < confinementRect.bottom()) {
 
417
            y = qMin(y + moveY, confinementRect.bottom() + 1 - geom.height()); // +1 because QRect::bottom() weird
 
418
        }
 
419
    } else {
 
420
        if (geom.y() > confinementRect.top()) {
 
421
            y = qMax(y + moveY, confinementRect.top());
 
422
        }
 
423
    }
 
424
 
 
425
    geom.moveTo(x, y);
 
426
    return toMirRectangle(geom.marginsRemoved(windowMargins));
 
427
}