Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Has anyone worked around iOS safe zone margins, like with iPhone X?



  • UIKit in iOS 11 has new features for laying out your main view without overlapping built-in device controls and bezels, for example on the iPhone X. Has anyone played out their widgets according to these? I have some strange behavior with my QGraphicsView and QWidget overlays, which should be full screen (see screenshot):

    0_1560500680588_Untitled 2.png

    0_1560500778275_Untitled 3.png

    0_1560500753761_Untitled 4.png

    I suppose I would like to know what the margins are and also how to prevent my view from automatically being restricted to the safe zone. Some elements need to be drawn differently, and some simply need to go outside the safe zones to the actual edges of the screen.

    Here are two links describing how to handle this in swift:

    1. iOS Safe Area

    2. How to Handle Safe Area Insets, Notch & Display Cutout for iPhone X, iPad X and Android P – 2019



  • Hi @patrickkidd

    These links might help you.

    Sample code for QML.

    ApplicationWindow {
        id: root
    
        flags: Qt.Window | Qt.WindowTitleHint | Qt.WindowSystemMenuHint
               | (Qt.platform.os === "ios" ? Qt.MaximizeUsingFullscreenGeometryHint : 0)
    }
    
    // This function is to support the iPhone X Series notch issue - status bar size is 44pt
        function toolbarMarginSupport() {
            if (isIPad || (Qt.platform.os === "ios" && isPortraitMode)) {
                switch(windowScreen.height * windowScreen.devicePixelRatio) {
                case 1624: // iPhone_XR (Qt Provided Physical Resolution);
                case 1792: // iPhone_XR;
                case 2436: // iPhone_X_XS;
                case 2688: // iPhone_XS_MAX;
                    return 44;
                default:
                    return 20;
                }
            } else {
                return 0;
            }
        }
    
        function isIPhoneXSeries() {
            if (isIPad || (Qt.platform.os === "ios" && isPortraitMode)) {
                switch(windowScreen.height * windowScreen.devicePixelRatio) {
                case 1624: // iPhone_XR (Qt Provided Physical Resolution);
                case 1792: // iPhone_XR;
                case 2436: // iPhone_X_XS;
                case 2688: // iPhone_XS_MAX;
                    return true;
                default:
                    return false;
                }
            } else {
                return false;
            }
        }
    

    All the best.


  • Moderators

    @patrickkidd

    this workaround works

    https://bugreports.qt.io/browse/QTBUG-64574

    but make sure, to delay the reading after a orientation change

    https://bugreports.qt.io/browse/QTBUG-76234



  • Hi @patrickkidd ,

    • Here is a sample code,which will return you the notch values:-

      QPlatformWindow *platformWindow = static_cast<QPlatformWindow *>(window->handle());
      QMargins margins = platformWindow->safeAreaMargins();
      int topMargin = 0;
      int bottomMorgin = 0;
      int leftMargin = 0;
      int rightMargin = 0;
      topMargin = margins.top();
      rightMargin = margins.right();
      bottomMorgin = margins.bottom();
      leftMargin = margins.left();

    • You need also need to set this:-

      window.setFlag(Qt::MaximizeUsingFullscreenGeometryHint, true);


  • All very helpful and interesting responses.

    Looks like Qt.MaximizeUsingFullscreenGeometryHint doesn't have an effect. I am using a QMainWindow for my top-level widget with no other flags set.


  • Moderators

    @patrickkidd
    if you're working with QWidgtes, and your TopMost Widget is a QMainWindow. Then simply set a Layout to the central widget.

    By default the layout respects the safe margins

    0_1560502580696_IMG_0515.PNG



  • @J.Hilk Can you paste a code snippet? When you say "set a Layout to the central widget," do you mean 1) layout the central widget as in my .ui file:

            self.centralWidget = QtWidgets.QWidget(MainWindow)
            self.centralWidget.setObjectName("centralWidget")
            self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralWidget)
    

    or 2) lay out the QMainWindow and add the central widget:

            self.ui.centralWidget = QOpenGLWidget(self)
            self.setCentralWidget(self.ui.centralWidget)
            Layout = QVBoxLayout(self)
            Layout.setContentsMargins(0, 0, 0, 0)
            Layout.addWidget(self.ui.centralWidget)
    

    When I run #2 it gives the following warning and the app runs on Mac but only shows a white screen (within the safe zone) on iOS. There is no layout explicitly added so it must be implicit in QMainWindow:

    kernel/qlayout.cpp(148): QLayout: Attempting to add QLayout "" to MainWindow "", which already has a layout
    

  • Moderators

    @patrickkidd
    Sadly I have next to no experience with the python bindings

    but here's a simple c++ example (everything in main)

    #include <QApplication>
    
    #include <QVBoxLayout>
    #include <QDebug>
    #include <QWidget>
    #include <QPainter>
    
    class Widget : public QWidget
    {
        Q_OBJECT
    
    public:
        Widget(QWidget *parent = nullptr) : QWidget(parent)
        {
            setStyleSheet("background-color:transparent;");
        }
        ~Widget() = default;
    
        void setGridDistance(int distance)
        {
            m_GridDistance = distance;
            update();
        }
    
    protected:
        void paintEvent(QPaintEvent *event)
        {
            QWidget::paintEvent(event);
    
            QPainter p(this);
            p.setPen(QPen(Qt::white,3));
            for(int i(0); i < width(); i += m_GridDistance){
                p.drawLine(i,0,i,height());
            }
    
            for(int i(0); i < height(); i += m_GridDistance){
                p.drawLine(0,i,width(),i);
            }
        }
    
        int m_GridDistance = 20;
    };
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        QWidget *w = new QWidget();
        w->setStyleSheet("background-color:red;");
        w->setWindowFlag(Qt::MaximizeUsingFullscreenGeometryHint,true);
        w->setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea,false);
        w->showFullScreen();
    
        Widget *wChild = new Widget(w);
        wChild->setStyleSheet("background-color:transparent;");
    
        //!Does not work
        {
            QVBoxLayout *layout = new QVBoxLayout(w);
            layout->setSizeConstraint(QLayout::SetNoConstraint);
            layout->setMargin(0);
            layout->addWidget(wChild);
        }
    
        //!Works
        {
    //        wChild->resize(w->size());
    //        wChild->show();
        }
    
        return a.exec();
    }
    
    

    the normal QWidget spans the whole screen, the wChild widget only inside the save margins, due to the layout

    Ignore the extra part, commended , parts IIRC that is for an other issue x)



  • @J.Hilk said in Has anyone worked around iOS safe zone margins, like with iPhone X?:

    w->setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea,false);
    

    It looks like this was the line to do it. The Qt::MaximizeUsingFullscreenGeometryHint didn't have any effect. I didn't call showFullScreen().

    So now it will just be a matter of getting the margins from QPlatformWindow using the example from the following if I can only figure out the include for QPlatformWindow. <qpa/qplatformwindow.h> doesn't seem to work:

    @Shrinidhi-Upadhyaya

    QPlatformWindow *platformWindow = static_cast<QPlatformWindow *>(window->handle());
    QMargins margins = platformWindow->safeAreaMargins();
    

    Any idea what the include is for QPlatformWindow?


  • Moderators

    @patrickkidd said in Has anyone worked around iOS safe zone margins, like with iPhone X?:

    Any idea what the include is for QPlatformWindow?

    inside your *.pro file you need to include this module: QT += gui-private

    then this include is available:
    #include <QtGui/qpa/qplatformwindow.h>


Log in to reply