Warning, /graphics/krita/3rdparty/ext_qt/0038-Android-Add-window-manager-for-raster-based-QWidgets.patch is written in an unsupported language. File is not indexed.

0001 From 028b108866e82230dd3f7219ff4c1b4bbbc81004 Mon Sep 17 00:00:00 2001
0002 From: Sharaf Zaman <sharafzaz121@gmail.com>
0003 Date: Thu, 15 Apr 2021 21:35:50 +0000
0004 Subject: [PATCH] Android: Add window manager for raster based QWidgets
0005 
0006 The way this works is for window types: (Qt::Dialog || Qt::Tool (without
0007 Qt::FramelessWindowHint)) which on other platforms are typically
0008 expected to have a frame around them; Before we add them to window stack
0009 we add another window which we call Window Manager, this window is
0010 offsetted by specific value and is white which makes it look like a
0011 window manager. We also handle events on this window, using which we can
0012 currently move the window around.
0013 
0014 The window is rendered like any other window which does not have
0015 renderToTexture enabled.
0016 ---
0017  src/plugins/platforms/android/android.pro     |   6 +-
0018  .../platforms/android/androidjniinput.cpp     |  10 +-
0019  .../android/qandroidplatformbackingstore.cpp  |  13 +-
0020  .../android/qandroidplatformbackingstore.h    |   2 +-
0021  .../android/qandroidplatformopenglwindow.cpp  |  16 +-
0022  .../android/qandroidplatformscreen.cpp        |  51 ++++-
0023  .../android/qandroidplatformscreen.h          |   4 +
0024  .../android/qandroidplatformwindow.cpp        |   1 +
0025  .../android/qandroidplatformwindow.h          |   1 -
0026  .../android/qandroidplatformwindowmanager.cpp | 214 ++++++++++++++++++
0027  .../android/qandroidplatformwindowmanager.h   |  59 +++++
0028  11 files changed, 359 insertions(+), 18 deletions(-)
0029  create mode 100644 src/plugins/platforms/android/qandroidplatformwindowmanager.cpp
0030  create mode 100644 src/plugins/platforms/android/qandroidplatformwindowmanager.h
0031 
0032 diff --git a/src/plugins/platforms/android/android.pro b/src/plugins/platforms/android/android.pro
0033 index 78632a9bea..8f62cb4c1e 100644
0034 --- a/src/plugins/platforms/android/android.pro
0035 +++ b/src/plugins/platforms/android/android.pro
0036 @@ -48,7 +48,8 @@ SOURCES += $$PWD/androidplatformplugin.cpp \
0037             $$PWD/qandroidplatformforeignwindow.cpp \
0038             $$PWD/qandroideventdispatcher.cpp \
0039             $$PWD/qandroidplatformoffscreensurface.cpp \
0040 -           $$PWD/qandroidplatformfiledialoghelper.cpp
0041 +           $$PWD/qandroidplatformfiledialoghelper.cpp \
0042 +           $$PWD/qandroidplatformwindowmanager.cpp
0043  
0044  HEADERS += $$PWD/qandroidplatformintegration.h \
0045             $$PWD/androidcontentfileengine.h \
0046 @@ -79,7 +80,8 @@ HEADERS += $$PWD/qandroidplatformintegration.h \
0047             $$PWD/qandroidplatformforeignwindow.h \
0048             $$PWD/qandroideventdispatcher.h \
0049             $$PWD/qandroidplatformoffscreensurface.h \
0050 -           $$PWD/qandroidplatformfiledialoghelper.h
0051 +           $$PWD/qandroidplatformfiledialoghelper.h \
0052 +           $$PWD/qandroidplatformwindowmanager.h
0053  
0054  qtConfig(android-style-assets): SOURCES += $$PWD/extract.cpp
0055  else: SOURCES += $$PWD/extract-dummy.cpp
0056 diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp
0057 index fec394f95e..257d013fa8 100644
0058 --- a/src/plugins/platforms/android/androidjniinput.cpp
0059 +++ b/src/plugins/platforms/android/androidjniinput.cpp
0060 @@ -355,7 +355,10 @@ namespace QtAndroidInput
0061  #if QT_CONFIG(tabletevent)
0062          QPointF globalPosF(x, y);
0063          QPoint globalPos((int)x, (int)y);
0064 -        QWindow *tlw = topLevelWindowAt(globalPos);
0065 +        QWindow *tlw = m_mouseGrabber.data();
0066 +        if (!tlw) {
0067 +            tlw = topLevelWindowAt(globalPos);
0068 +        }
0069  
0070          QPointF localPos = globalPosF;
0071          if (tlw) {
0072 @@ -381,10 +384,13 @@ namespace QtAndroidInput
0073          Qt::MouseButtons buttons = Qt::NoButton;
0074          switch (action) {
0075          case AMOTION_EVENT_ACTION_UP:
0076 +            m_mouseGrabber = nullptr;
0077              buttons = Qt::NoButton;
0078              break;
0079 -        case AMOTION_EVENT_ACTION_MOVE:
0080          case AMOTION_EVENT_ACTION_DOWN:
0081 +            m_mouseGrabber = tlw;
0082 +            // fall through
0083 +        case AMOTION_EVENT_ACTION_MOVE:
0084              if (!buttonState)
0085                  buttons = Qt::LeftButton;
0086          default:
0087 diff --git a/src/plugins/platforms/android/qandroidplatformbackingstore.cpp b/src/plugins/platforms/android/qandroidplatformbackingstore.cpp
0088 index 61d4969c41..75f9b41342 100644
0089 --- a/src/plugins/platforms/android/qandroidplatformbackingstore.cpp
0090 +++ b/src/plugins/platforms/android/qandroidplatformbackingstore.cpp
0091 @@ -42,6 +42,7 @@
0092  #include "qandroidplatformscreen.h"
0093  #include "qandroidplatformwindow.h"
0094  #include <qpa/qplatformscreen.h>
0095 +#include <private/qhighdpiscaling_p.h>
0096  
0097  QT_BEGIN_NAMESPACE
0098  
0099 @@ -54,6 +55,7 @@ QAndroidPlatformBackingStore::QAndroidPlatformBackingStore(QWindow *window)
0100  
0101  QPaintDevice *QAndroidPlatformBackingStore::paintDevice()
0102  {
0103 +    Q_ASSERT(!m_image.isNull());
0104      return &m_image;
0105  }
0106  
0107 @@ -71,8 +73,17 @@ void QAndroidPlatformBackingStore::resize(const QSize &size, const QRegion &stat
0108  {
0109      Q_UNUSED(staticContents);
0110  
0111 -    if (m_image.size() != size)
0112 +    if (m_image.size() != size) {
0113          m_image = QImage(size, window()->screen()->handle()->format());
0114 +    }
0115 +}
0116 +
0117 +QImage QAndroidPlatformBackingStore::toImage() const
0118 +{
0119 +    if (m_image.isNull()) {
0120 +        qDebug() << "QAndroidPlatformBackingStore::toImage(): image is null";
0121 +    }
0122 +    return m_image;
0123  }
0124  
0125  void QAndroidPlatformBackingStore::setBackingStore(QWindow *window)
0126 diff --git a/src/plugins/platforms/android/qandroidplatformbackingstore.h b/src/plugins/platforms/android/qandroidplatformbackingstore.h
0127 index a3a65aa30e..ec1761c789 100644
0128 --- a/src/plugins/platforms/android/qandroidplatformbackingstore.h
0129 +++ b/src/plugins/platforms/android/qandroidplatformbackingstore.h
0130 @@ -53,7 +53,7 @@ public:
0131      QPaintDevice *paintDevice() override;
0132      void flush(QWindow *window, const QRegion &region, const QPoint &offset) override;
0133      void resize(const QSize &size, const QRegion &staticContents) override;
0134 -    QImage toImage() const override { return m_image; }
0135 +    QImage toImage() const override;
0136      void setBackingStore(QWindow *window);
0137  protected:
0138      QImage m_image;
0139 diff --git a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
0140 index 3de5d30623..35b437dd59 100644
0141 --- a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
0142 +++ b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
0143 @@ -82,17 +82,18 @@ void QAndroidPlatformOpenGLWindow::repaint(const QRegion &region)
0144  
0145      QRect currentGeometry = geometry();
0146  
0147 -    QRect dirtyClient = region.boundingRect();
0148 -    QRect dirtyRegion(currentGeometry.left() + dirtyClient.left(),
0149 -                      currentGeometry.top() + dirtyClient.top(),
0150 -                      dirtyClient.width(),
0151 -                      dirtyClient.height());
0152 +    QRect dirtyClient = region.boundingRect(); // not sure if this is necessary
0153 +    QRegion dirtyRegion = dirtyClient;
0154 +    dirtyRegion += currentGeometry;
0155 +
0156      QRect mOldGeometryLocal = m_oldGeometry;
0157      m_oldGeometry = currentGeometry;
0158      // If this is a move, redraw the previous location
0159      if (mOldGeometryLocal != currentGeometry)
0160          platformScreen()->setDirty(mOldGeometryLocal);
0161 -    platformScreen()->setDirty(dirtyRegion);
0162 +    for (const auto &dirtyRect : dirtyRegion) {
0163 +        platformScreen()->setDirty(dirtyRect);
0164 +    }
0165  }
0166  
0167  void QAndroidPlatformOpenGLWindow::setGeometry(const QRect &rect)
0168 @@ -116,8 +117,7 @@ void QAndroidPlatformOpenGLWindow::setGeometry(const QRect &rect)
0169          QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), rect.size()));
0170      }
0171  
0172 -    if (rect.topLeft() != m_oldGeometry.topLeft())
0173 -        repaint(QRegion(rect));
0174 +    repaint(QRegion(rect));
0175  }
0176  
0177  EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config)
0178 diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp
0179 index 4213bdc088..0100050bb9 100644
0180 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp
0181 +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp
0182 @@ -50,6 +50,7 @@
0183  #include "androidjnimain.h"
0184  #include "androidjnimenu.h"
0185  #include "androiddeadlockprotector.h"
0186 +#include "qandroidplatformwindowmanager.h"
0187  
0188  #include <android/bitmap.h>
0189  #include <android/native_window_jni.h>
0190 @@ -162,6 +163,15 @@ void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window)
0191      if (window->parent() && window->isRaster())
0192          return;
0193  
0194 +    if ((window->window()->type() == Qt::Dialog || window->window()->type() == Qt::Tool)
0195 +        && (window->window()->flags() & Qt::FramelessWindowHint) == 0) {
0196 +        // we will manage memory ourselves, because our parent is always
0197 +        // MainWindow
0198 +        QAndroidPlatformWindowManager *wm = new QAndroidPlatformWindowManager(window);
0199 +        wm->show();
0200 +        m_windowManagers.insert(window->winId(), wm);
0201 +    }
0202 +
0203      Q_ASSERT(!m_windowStack.contains(window));
0204      m_windowStack.prepend(window);
0205      if (window->isRaster()) {
0206 @@ -179,6 +189,12 @@ void QAndroidPlatformScreen::removeWindow(QAndroidPlatformWindow *window)
0207      if (window->parent() && window->isRaster())
0208          return;
0209  
0210 +    if (m_windowManagers.contains(window->winId())) {
0211 +        QAndroidPlatformWindowManager *wm = m_windowManagers[window->winId()];
0212 +        m_windowManagers.remove(window->winId());
0213 +        wm->close();
0214 +        delete wm;
0215 +    }
0216  
0217      Q_ASSERT(m_windowStack.contains(window));
0218      m_windowStack.removeOne(window);
0219 @@ -203,6 +219,9 @@ void QAndroidPlatformScreen::raise(QAndroidPlatformWindow *window)
0220      if (index <= 0)
0221          return;
0222      m_windowStack.move(index, 0);
0223 +    if (m_windowManagers.contains(window->winId())) {
0224 +        m_windowStack.move(index + 1, 1);
0225 +    }
0226      if (window->isRaster()) {
0227          setDirty(window->geometry());
0228      }
0229 @@ -217,9 +236,25 @@ void QAndroidPlatformScreen::lower(QAndroidPlatformWindow *window)
0230          return;
0231  
0232      int index = m_windowStack.indexOf(window);
0233 -    if (index == -1 || index == (m_windowStack.size() - 1))
0234 +    if (index == -1)
0235 +        return;
0236 +
0237 +    // check if current window is not the last window
0238 +    if (m_windowManagers.contains(window->winId())) {
0239 +        if (index != (m_windowStack.size() - 2)) {
0240 +            // we first move the actual window to last
0241 +            m_windowStack.move(index, m_windowStack.size() - 1);
0242 +            // then we move the window manager window
0243 +            m_windowStack.move(index, m_windowStack.size() - 1);
0244 +        } else {
0245 +            return;
0246 +        }
0247 +    } else if (index != (m_windowStack.size() - 1)) {
0248 +        m_windowStack.move(index, m_windowStack.size() - 1);
0249 +    } else {
0250          return;
0251 -    m_windowStack.move(index, m_windowStack.size() - 1);
0252 +    }
0253 +
0254      if (window->isRaster()) {
0255          setDirty(window->geometry());
0256      }
0257 @@ -228,6 +263,14 @@ void QAndroidPlatformScreen::lower(QAndroidPlatformWindow *window)
0258      topWindowChanged(w);
0259  }
0260  
0261 +
0262 +void QAndroidPlatformScreen::setWindowGeometry(QAndroidPlatformWindow *window, const QRect &rect)
0263 +{
0264 +    if (m_windowManagers.contains(window->winId())) {
0265 +        m_windowManagers[window->winId()]->updateGeometry(rect);
0266 +    }
0267 +}
0268 +
0269  void QAndroidPlatformScreen::scheduleUpdate()
0270  {
0271      if (!m_updatePending) {
0272 @@ -399,13 +442,15 @@ void QAndroidPlatformScreen::doRedraw()
0273              visibleRegion -= targetRect;
0274              QRect windowRect = targetRect.translated(-window->geometry().topLeft());
0275              QAndroidPlatformBackingStore *backingStore = static_cast<QAndroidPlatformWindow *>(window)->backingStore();
0276 +
0277              if (backingStore)
0278                  compositePainter.drawImage(targetRect.topLeft(), backingStore->toImage(), windowRect);
0279          }
0280      }
0281  
0282 -    for (const QRect &rect : visibleRegion)
0283 +    for (const QRect &rect : visibleRegion) {
0284          compositePainter.fillRect(rect, QColor(Qt::transparent));
0285 +    }
0286  
0287      ret = ANativeWindow_unlockAndPost(m_nativeSurface);
0288      if (ret >= 0)
0289 diff --git a/src/plugins/platforms/android/qandroidplatformscreen.h b/src/plugins/platforms/android/qandroidplatformscreen.h
0290 index f15aeae3fd..415fcfc932 100644
0291 --- a/src/plugins/platforms/android/qandroidplatformscreen.h
0292 +++ b/src/plugins/platforms/android/qandroidplatformscreen.h
0293 @@ -54,6 +54,7 @@
0294  
0295  QT_BEGIN_NAMESPACE
0296  
0297 +class QAndroidPlatformWindowManager;
0298  class QAndroidPlatformWindow;
0299  
0300  class QAndroidPlatformScreen: public QObject, public QPlatformScreen, public AndroidSurfaceClient
0301 @@ -77,6 +78,8 @@ public:
0302      void removeWindow(QAndroidPlatformWindow *window);
0303      void raise(QAndroidPlatformWindow *window);
0304      void lower(QAndroidPlatformWindow *window);
0305 +    /// @param rect should be in native pixels
0306 +    void setWindowGeometry(QAndroidPlatformWindow *window, const QRect &rect);
0307  
0308      void scheduleUpdate();
0309      void topWindowChanged(QWindow *w);
0310 @@ -119,6 +122,7 @@ private:
0311      ANativeWindow* m_nativeSurface = nullptr;
0312      QWaitCondition m_surfaceWaitCondition;
0313      QSize m_size;
0314 +    QMap<int, QAndroidPlatformWindowManager *> m_windowManagers;
0315  };
0316  
0317  QT_END_NAMESPACE
0318 diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp
0319 index 61e6f360de..1574b8b013 100644
0320 --- a/src/plugins/platforms/android/qandroidplatformwindow.cpp
0321 +++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp
0322 @@ -73,6 +73,7 @@ void QAndroidPlatformWindow::raise()
0323  void QAndroidPlatformWindow::setGeometry(const QRect &rect)
0324  {
0325      QWindowSystemInterface::handleGeometryChange(window(), rect);
0326 +    platformScreen()->setWindowGeometry(this, rect);
0327  }
0328  
0329  void QAndroidPlatformWindow::setVisible(bool visible)
0330 diff --git a/src/plugins/platforms/android/qandroidplatformwindow.h b/src/plugins/platforms/android/qandroidplatformwindow.h
0331 index f2e51bd3df..aad001c359 100644
0332 --- a/src/plugins/platforms/android/qandroidplatformwindow.h
0333 +++ b/src/plugins/platforms/android/qandroidplatformwindow.h
0334 @@ -86,7 +86,6 @@ public:
0335  
0336      virtual void repaint(const QRegion &) { }
0337  
0338 -protected:
0339      void setGeometry(const QRect &rect) override;
0340  
0341  protected:
0342 diff --git a/src/plugins/platforms/android/qandroidplatformwindowmanager.cpp b/src/plugins/platforms/android/qandroidplatformwindowmanager.cpp
0343 new file mode 100644
0344 index 0000000000..15bdae76a5
0345 --- /dev/null
0346 +++ b/src/plugins/platforms/android/qandroidplatformwindowmanager.cpp
0347 @@ -0,0 +1,214 @@
0348 +#include "qandroidplatformwindowmanager.h"
0349 +
0350 +#include "qandroidplatformwindow.h"
0351 +#include "qandroidplatformbackingstore.h"
0352 +
0353 +#include <private/qhighdpiscaling_p.h>
0354 +#include <QPainter>
0355 +#include <qbackingstore.h>
0356 +
0357 +// In HighDPI
0358 +static const int paddingTop = 25;
0359 +static const int paddingLBR = 3; // left, bottom and right
0360 +
0361 +QAndroidPlatformWindowManager::QAndroidPlatformWindowManager(QAndroidPlatformWindow *window)
0362 +    : QWindow(window->window()->parent())
0363 +    , m_realWindow(window)
0364 +    , m_backingStore(new QAndroidPlatformBackingStore(this))
0365 +{
0366 +    setObjectName("QAndroidPlatformWindowManager");
0367 +    // popup because they are special, frameless because recursion
0368 +    setFlags(Qt::Popup | Qt::FramelessWindowHint);
0369 +    setMinimumSize(window->window()->minimumSize());
0370 +    setMaximumSize(window->window()->maximumSize());
0371 +}
0372 +
0373 +QAndroidPlatformWindowManager::~QAndroidPlatformWindowManager()
0374 +{
0375 +    delete m_backingStore;
0376 +}
0377 +
0378 +void QAndroidPlatformWindowManager::updateGeometry(const QRect &rect)
0379 +{
0380 +    if (m_oldChildGeometry == rect) {
0381 +        return;
0382 +    }
0383 +    m_oldChildGeometry = rect;
0384 +    QRect wmGeometry = QHighDpi::fromNativePixels(rect, m_realWindow->window());
0385 +    wmGeometry.translate(-paddingLBR, -paddingTop);
0386 +    wmGeometry.setSize({ 2 * paddingLBR + wmGeometry.width(),
0387 +                            paddingLBR + wmGeometry.height() + paddingTop });
0388 +
0389 +    setGeometry(wmGeometry);
0390 +    resize(QHighDpi::toNativePixels(geometry().size(), this));
0391 +}
0392 +
0393 +void QAndroidPlatformWindowManager::mousePressEvent(QMouseEvent *event)
0394 +{
0395 +    m_startingPoint = event->globalPos();
0396 +    m_realWindowOffset = m_startingPoint - m_realWindow->window()->geometry().topLeft();
0397 +    m_startingGeometry = m_realWindow->window()->geometry();
0398 +
0399 +    calculatePressArea(event->globalPos());
0400 +
0401 +    m_mousePressed = true;
0402 +    event->accept();
0403 +}
0404 +
0405 +void QAndroidPlatformWindowManager::calculatePressArea(const QPoint &pos)
0406 +{
0407 +    QRect wmGeom = geometry();
0408 +    QRect childGeom = m_realWindow->window()->geometry();
0409 +
0410 +    // NOTE: we add + 1 because of QRect's quirks
0411 +    if (QRect(wmGeom.topLeft(), QSize(wmGeom.width(), paddingTop)).contains(pos)) {
0412 +        m_grabbedAction = MOVE;
0413 +    } else if (QRect(wmGeom.topLeft(), QSize(paddingLBR, wmGeom.height()))
0414 +                   .contains(pos)) {
0415 +        m_grabbedAction = HORIZONTAL_RESIZE_LEFT;
0416 +    } else if (QRect({childGeom.right() + 1, childGeom.top()},
0417 +                     QSize(paddingLBR, wmGeom.height()))
0418 +                   .contains(pos)) {
0419 +        m_grabbedAction = HORIZONTAL_RESIZE_RIGHT;
0420 +    } else if (QRect({childGeom.left(), childGeom.bottom() + 1}, childGeom.size())
0421 +                   .contains(pos)) {
0422 +        m_grabbedAction = VERTICAL_RESIZE;
0423 +    }
0424 +
0425 +    int cornerPadding = 10; // this makes corners a bit easier to grab
0426 +
0427 +    if (QRect(childGeom.translated(-cornerPadding, -cornerPadding).bottomRight(),
0428 +              QPoint(wmGeom.right() + 1, wmGeom.bottom() + 1))
0429 +            .contains(pos)) {
0430 +        m_grabbedAction = CORNER_RESIZE_RIGHT;
0431 +    }
0432 +
0433 +    QPoint startOffset = QPoint(wmGeom.left(), childGeom.bottom() - cornerPadding);
0434 +    if (QRect(startOffset, QPoint(childGeom.left() + cornerPadding, wmGeom.bottom()))
0435 +            .contains(pos)) {
0436 +        m_grabbedAction = CORNER_RESIZE_LEFT;
0437 +    }
0438 +}
0439 +
0440 +void QAndroidPlatformWindowManager::mouseMoveEvent(QMouseEvent *event)
0441 +{
0442 +    if (m_mousePressed) {
0443 +        move(event->globalPos());
0444 +        event->accept();
0445 +    }
0446 +}
0447 +
0448 +void QAndroidPlatformWindowManager::mouseReleaseEvent(QMouseEvent *event)
0449 +{
0450 +    m_mousePressed = false;
0451 +    m_grabbedAction = NONE;
0452 +
0453 +    event->accept();
0454 +}
0455 +
0456 +void QAndroidPlatformWindowManager::resizeEvent(QResizeEvent *event)
0457 +{
0458 +    resize(event->size());
0459 +}
0460 +
0461 +void QAndroidPlatformWindowManager::showEvent(QShowEvent *event)
0462 +{
0463 +    if (m_realWindow->geometry().topLeft().y() < paddingTop) {
0464 +        QRect geom = m_realWindow->geometry();
0465 +        geom.translate(0, paddingTop);
0466 +        m_realWindow->setGeometry(geom);
0467 +    }
0468 +
0469 +    updateGeometry(m_realWindow->geometry());
0470 +
0471 +    setWindowState(Qt::WindowNoState);
0472 +    // NOTE: platformWindow won't be created yet, so set flags for it.
0473 +    // popup because they are special, frameless because recursion
0474 +    setFlags(Qt::Popup | Qt::FramelessWindowHint);
0475 +
0476 +    event->accept();
0477 +}
0478 +
0479 +void QAndroidPlatformWindowManager::repaint()
0480 +{
0481 +    QRect childGeometry = handle()->geometry();
0482 +    QAndroidPlatformWindow *platformWindow = static_cast<QAndroidPlatformWindow *>(handle());
0483 +    platformWindow->setBackingStore(m_backingStore);
0484 +
0485 +    QPainter painter(m_backingStore->paintDevice());
0486 +    painter.fillRect(0, 0, childGeometry.width(), childGeometry.height(), Qt::white);
0487 +    m_backingStore->endPaint();
0488 +
0489 +    // m_backingStore->toImage().save(QString("/data/data/org.krita/files/%1.png").arg(this->objectName()));
0490 +}
0491 +
0492 +void QAndroidPlatformWindowManager::move(const QPoint &pos)
0493 +{
0494 +    switch (m_grabbedAction) {
0495 +    case MOVE:
0496 +        m_realWindow->window()->setPosition(QPoint(pos.x(), std::max(10, pos.y()))
0497 +                                            - m_realWindowOffset);
0498 +        break;
0499 +    case HORIZONTAL_RESIZE_LEFT:
0500 +        resizeChildWindow(QRect(pos.x(), m_startingGeometry.y(),
0501 +                                m_startingGeometry.right() - pos.x(),
0502 +                                m_startingGeometry.height()));
0503 +        break;
0504 +    case HORIZONTAL_RESIZE_RIGHT:
0505 +        resizeChildWindow(QRect(m_startingGeometry.left(), m_startingGeometry.top(),
0506 +                                (pos.x() - m_startingGeometry.left()),
0507 +                                m_startingGeometry.height()));
0508 +        break;
0509 +    case VERTICAL_RESIZE:
0510 +        resizeChildWindow(QRect(m_startingGeometry.left(), m_startingGeometry.top(),
0511 +                                m_startingGeometry.width(),
0512 +                                (pos.y() - m_startingGeometry.top())));
0513 +        break;
0514 +    case CORNER_RESIZE_LEFT:
0515 +        resizeChildWindow(QRect(pos.x(), m_startingGeometry.y(),
0516 +                                m_startingGeometry.right() - pos.x(),
0517 +                                pos.y() - m_startingGeometry.top()));
0518 +        break;
0519 +    case CORNER_RESIZE_RIGHT:
0520 +        resizeChildWindow(QRect(m_startingGeometry.left(), m_startingGeometry.top(),
0521 +                                (pos.x() - m_startingGeometry.left()),
0522 +                                (pos.y() - m_startingGeometry.top())));
0523 +        break;
0524 +    default:
0525 +        qWarning() << "WindowManager: Bad Action" << m_grabbedAction;
0526 +        break;
0527 +    }
0528 +}
0529 +
0530 +void QAndroidPlatformWindowManager::resize(const QSize &size)
0531 +{
0532 +    if (m_oldSize == size) {
0533 +        return;
0534 +    }
0535 +    m_oldSize = size;
0536 +    m_backingStore->resize(QHighDpi::toNativePixels(size, this), QRegion());
0537 +    repaint();
0538 +}
0539 +
0540 +void QAndroidPlatformWindowManager::resizeChildWindow(const QRect &geom)
0541 +{
0542 +    QRect adjustedGeom = geom;
0543 +    if (adjustedGeom.width() < minimumWidth()) {
0544 +        adjustedGeom.setLeft(m_realWindow->window()->geometry().left());
0545 +        adjustedGeom.setWidth(minimumWidth());
0546 +    }
0547 +    if (adjustedGeom.height() < minimumHeight()) {
0548 +        adjustedGeom.setTop(m_realWindow->window()->geometry().top());
0549 +        adjustedGeom.setHeight(minimumHeight());
0550 +    }
0551 +
0552 +    adjustedGeom.setWidth(adjustedGeom.width() > maximumWidth() ? maximumWidth()
0553 +                                                                : adjustedGeom.width());
0554 +
0555 +    adjustedGeom.setHeight(adjustedGeom.height() > maximumHeight()
0556 +                               ? maximumHeight()
0557 +                               : adjustedGeom.height());
0558 +
0559 +    // this will trigger window manager's updateGeometry as well
0560 +    m_realWindow->window()->setGeometry(adjustedGeom);
0561 +}
0562 diff --git a/src/plugins/platforms/android/qandroidplatformwindowmanager.h b/src/plugins/platforms/android/qandroidplatformwindowmanager.h
0563 new file mode 100644
0564 index 0000000000..0688a75794
0565 --- /dev/null
0566 +++ b/src/plugins/platforms/android/qandroidplatformwindowmanager.h
0567 @@ -0,0 +1,59 @@
0568 +#ifndef __QANDROIDPLATFORMWINDOWMANAGER_H_
0569 +#define __QANDROIDPLATFORMWINDOWMANAGER_H_
0570 +
0571 +#include <qpa/qplatformwindow.h>
0572 +
0573 +class QAndroidPlatformWindow;
0574 +class QAndroidPlatformBackingStore;
0575 +
0576 +class QAndroidPlatformWindowManager: public QWindow {
0577 +private:
0578 +    enum WM_ACTION {
0579 +        MOVE = 0,
0580 +        HORIZONTAL_RESIZE_LEFT,
0581 +        HORIZONTAL_RESIZE_RIGHT,
0582 +        VERTICAL_RESIZE,
0583 +        CORNER_RESIZE_LEFT,
0584 +        CORNER_RESIZE_RIGHT,
0585 +        NONE
0586 +    };
0587 +public:
0588 +    QAndroidPlatformWindowManager(QAndroidPlatformWindow *window = nullptr);
0589 +    ~QAndroidPlatformWindowManager();
0590 +
0591 +    /*
0592 +     * Updates the geometry of the window manager as per its child
0593 +     * @param geometry of window to be managed, rect should be in native pixels
0594 +     */
0595 +    void updateGeometry(const QRect &rect);
0596 +
0597 +protected:
0598 +    void resizeEvent(QResizeEvent *event) override;
0599 +    void showEvent(QShowEvent *event) override;
0600 +
0601 +    void mousePressEvent(QMouseEvent *event) override;
0602 +    void mouseMoveEvent(QMouseEvent *event) override;
0603 +    void mouseReleaseEvent(QMouseEvent *event) override;
0604 +
0605 +private:
0606 +    void repaint();
0607 +    void calculatePressArea(const QPoint &pos);
0608 +    void move(const QPoint &pos);
0609 +    void resize(const QSize &size);
0610 +    void resizeChildWindow(const QRect &geom);
0611 +
0612 +private:
0613 +    QAndroidPlatformWindow *m_realWindow;
0614 +    QAndroidPlatformBackingStore *m_backingStore;
0615 +
0616 +    QPoint m_startingPoint;
0617 +    QRect m_startingGeometry;
0618 +    QPoint m_realWindowOffset;
0619 +    QRect m_oldChildGeometry;
0620 +    QSize m_oldSize;
0621 +    bool m_mousePressed {false}; // because synthesized events
0622 +    WM_ACTION m_grabbedAction { NONE };
0623 +};
0624 +
0625 +
0626 +#endif // __QANDROIDPLATFORMWINDOWMANAGER_H_
0627 -- 
0628 2.34.1
0629