Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-125345

Safe area margins

    XMLWordPrintable

Details

    • Safe area margins
    • Android, iOS/tvOS/watchOS, macOS
    • 35cdd8abf (dev), 668914649 (dev), 074c812cb (6.7)

    Description

      Background

      Safe area (insets, margins, area) was a concept introduced initially on iOS. It is a representation of the area of a window/widget/view that the content can exist without potentially interfering with other parts of the system or application UI.

      For example, it's fine to paint a background outside of these areas, but an intractable element (button) should be placed inside the area, as placing it outside might prevent the user from pressing the button, or from triggering a system gesture in the area.

      The initial case for this on iOS was the system UI for the status bar, as well as the area of the screen where the user would initiate system gestures to open the app switcher.

      The safe area can differ depending on the device, and the current orientation of the device:

      In both cases above the safe area is relative to the screen, and since the app window is full screen the app window is affected.

      In more recent iOS version, on iPad OS, apps can run in windowed mode. This expands the concept a bit. The app window may not necessarily over/under-lap the screen's safe areas. But, the system may still reserve areas of the app window for system gestures and/or UI. 

      In this case, the three dots menu at the top, and the lower right corner used for resize gestures.

      Similarly, on visionOS, when running as iPad app:

      The safe area prevents user interface elements in the area that would interfere with the user looking at the system UI elements for resizing or moving the window, even if these controls are drawn outside of the window.

      Note how the traditional distinction between client area (app's window content) and non-client area (window titlebar/frame) does not apply for the iOS and visionOS cases. The client area extends to the entire application window, and the safe area is used to inform the app about which areas of the client area can be safely used without interfering with other content.

      Another example of this point is how the safe areas behave on macOS. There we have safe areas for both the view and the screen. The view's safe area typically matches the view's bounds, but setting the NSWindowStyleMaskFullSizeContentView style mask on the window, as well as titlebarAppearsTransparent, we get a similar situation as on iPadOS/visionOS:

      The title bar area is considered outside of the safe area of the view.

      We also have screen-relative safe areas, on Mac laptops that have a "notch" for the camera housing. 

      In this case, the application can go into fullscreen in a way that takes advantage of the full display area. The area obscured by the notch is then represented as the screen's non-safe area: (screenshot, so notch not visible )

      If the app wants to be even more granular, there are APIs that reflect the areas to the left and right of the notch that can still be used. This could possibly be a use-case for a future QRegion based safe area API, compared to the QMargins based API we have now, but is so far a corner case.

      Android

      Qt Widgets

      On the widgets side the safe area margins were hooked into the pre-existing QWidget concept of contentsMargins, as widgets already supported the notion of insetting the content (contentsRect) of the widget. By default the widget respects the safe area margins, combining the user's margins with the safe area margins in the resulting contentsMargins. 

      class MyWidget : public QWidget
      {
          void paintEvent(QPaintEvent *) override
          {
              QPainter painter(this);
              painter.fillRect(rect(), QGradient::Nega);
              painter.fillRect(contentsRect(), QGradient::SoftGrass);
          }
      };

      The user can override this with the Qt::WA_ContentsMarginsRespectsSafeArea widget attribute.

      Child widgets will also reflect the safe area margins correspondingly, unless they are placed inside the safe area margins. QLayout already takes the contentsRect of a widget into account when positioning widgets, so layouts will automatically respect the safe area margins as well. Layouts can opt out of this via the pre-existing Qt::WA_LayoutOnEntireRect attribute.

      In practice the result is that instead of the layout clashing with other UI elements (see title/zoom buttons):

      We get a layout that stays out of the non-safe area:

      Qt Quick

      Open Questions

      Attachments

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              vestbo Tor Arne Vestbø
              vestbo Tor Arne Vestbø
              Votes:
              2 Vote for this issue
              Watchers:
              8 Start watching this issue

              Dates

                Created:
                Updated:

                Gerrit Reviews

                  There are no open Gerrit changes