Skip to content

ASurface#

Root of a view tree that is displayed on some target: a window or an embedded surface.

Header:#include <AUI/Platform/ASurface.h>
CMake:aui_link(my_target PUBLIC aui::views)

Detailed Description#

ASurface is a AViewContainer that owns the rendering context and routes the input (pointer, keyboard, focus) to views. AWindow is the ASurface backed by a native window; embedding AUI into another application (i.e., SDL) uses a surface of its own.

ASurface::current() returns the surface which is being processed at the moment (i.e., the window a click handler belongs to). Typical operations:

  • focusNextView() moves the keyboard focus like Tab does;
  • blockUserInput() makes the surface ignore the user, i.e., while a modal dialog is shown;
  • createOverlappingSurface() creates a lightweight popup drawn over the contents (used by dropdown lists and menus).

Examples#

examples/ui/embedded_sdl/src/main.cpp

SDL3 — This code demonstrates how to integrate the AUI Framework with SDL3 to create a window with OpenGL rendering.

    ~EmbedRenderingContext() override {
    }

    void destroyNativeWindow(ASurface& window) override {}

    AImage makeScreenshot() override {
        return {};
    }
examples/7guis/circle_drawer/src/main.cpp

7GUIs Circle Drawer — Undo, redo, dialog control.

              .name = "Adjust radius...",
              .onAction =
                  [this, circle] {
                      auto radiusPopup = _new<AWindow>(
                          "", 200_dp, 50_dp, dynamic_cast<AWindow*>(ASurface::current()), WindowStyle::MODAL);
                      radiusPopup->setContents(Vertical {
                        Label { "Adjust diameter of circle at {}."_format(circle->position) },
                        Slider {
                          .value = AUI_REACT(circle->radius / MAX_RADIUS),
                          .onValueChanged =
examples/app/game_of_life/src/main.cpp

Game of Life — Game of Life implementation that uses advanced large dynamic data rendering techniques such as ITexture, AImage to be GPU friendly. The computation is performed in AThreadPool.

    _<ITexture> mTexture;

    void updateTexture() {
        if (!mTexture) {
            mTexture = ASurface::current()->getRenderingContext()->renderer().getNewTexture();
        }

        CellsImage image(mCells->size());
        for (unsigned y = 0; y < image.height(); ++y) {
            for (unsigned x = 0; x < image.width(); ++x) {
examples/app/notes/src/main.cpp

Notes App — Note taking app that demonstrates usage of AListModel, AProperty, user data saving and loading.

public:
    using ATextArea::ATextArea;
    void onCharEntered(AChar c) override {
        if (c == '\r') {
            ASurface::current()->focusNextView();
            return;
        }
        ATextArea::onCharEntered(c);
    }
};
examples/ui/contacts/src/view/ContactDetailsView.cpp

AUI Contacts — Usage of AUI_DECLARATIVE_FOR to make a contacts-like application.

        return;
    }

    // discard
    if (AMessageBox::show(dynamic_cast<AWindow*>(ASurface::current()), "Do you really want to discard?", "This action is irreversible!", AMessageBox::Icon::NONE, AMessageBox::Button::YES_NO) != AMessageBox::ResultButton::YES) {
        return;
    }
    mContact = mOriginalContact;
    mEditorMode = false;
}
examples/ui/views/src/ExampleWindow.cpp

Views Example — All-in-one views building example.

                  Label { "Scaling factor" },
                  Horizontal {
                    _new<ANumberPicker>().connect(&ANumberPicker::valueChanged,
                                                  [](int64_t x) {
                                                      ASurface::current()->setScalingParams(
                                                          { x * 0.25f,
                                                            std::nullopt });
                                                  }) AUI_LET {
                            it->setMin(1);
                            it->setMax(12);

Public Types#


Profiling#

struct ASurface::Profiling

Profiling (debugging) settings for this window. Can be controlled with devtools window.

AProperty<_weak<AView>> highlightView
View to highlight.
AProperty<bool> highlightRedrawRequests
Highlight redraw requests.
AProperty<bool> renderToTextureDecay
Visually displays render-to-texture caching by decreasing brightness of pixels that didn't updated in this frame. This effect may help to debug AView::redraw issues.
AProperty<bool> breakpointOnMarkMinContentSizeInvalid
When set to true, the next time window's requestLayout, debugger is invoked. Value is reset to false.
AProperty<bool> showBaseline
When set to true, all rendered strings will display their baselines.

ScalingParams#

struct ASurface::ScalingParams

Empty structure.

Public fields and Signals#


DOUBLECLICK_MAX_DURATION#

std::chrono::milliseconds DOUBLECLICK_MAX_DURATION

double click will be captured only if time elapsed since the previous click is less than DOUBLECLICK_MAX_DURATION


mForceUpdateCursorGuard#

bool mForceUpdateCursorGuard

If true, ASurface::forceUpdateCursor takes no action.


mPreventClickOnPointerRelease#

AOptional<bool> mPreventClickOnPointerRelease

ASurface::preventClickOnPointerRelease


touchscreenKeyboardHidden#

emits<> touchscreenKeyboardHidden

On touch screen keyboard hide.


touchscreenKeyboardShown#

emits<> touchscreenKeyboardShown

On touch screen keyboard show.

Public Methods#

blockUserInput#


virtual void ASurface::blockUserInput(bool blockUserInput = true)

Enables or disables user input for this window.

Arguments
blockUserInput
whether block user input or not.

Visually nothing changes, but when the user tries to interact with the window, nothing happens with the window and on some platforms a system sound played notifying the user that the window is blocked.

It is userful when you open a modal window and you want the user to complete the action in the modal window first in order to continue interacting with the parent window.

When displaying a modal dialog and has blocked the parent window, the application must unblock the parent window before the modal dialog destroyed, otherwise, another window will receive the keyboard focus and be activated.

createOverlappingSurface#


_<AOverlappingSurface> ASurface::createOverlappingSurface(const glm::ivec2& position, const glm::ivec2& size, bool closeOnClick = false)
Arguments
position
position where does the surface should be created. It's not exact the top left corner of the surface but a hint (i.e. if the surface does not fit)
size
size
closeOnClick
when true, overlapped surface is automatically closed when mouse clicked anywhere. It's usable for tooltips. Do not use that for context menus or other.
Returns
a new surface.

Creates a surface used for context menus and combo boxes. Closure of the surface is controlled by closeOnClick param but can be closed manually by calling closeOverlappingSurface.

auto surfaceContainer = ASurface::current()->createOverlappingSurface({0, 0}, {100, 100});

ALayoutInflater::inflate(surfaceContainer, Vertical {
    Button { Label { "Item1" } },
    Button { Label "Item2" } },
    Button { Label { "Item3" } },
});

surfaceContainer->pack();

To create overlapping surface below some view, use AView::getPositionInWindow:

auto surfaceContainer = ASurface::current()->createOverlappingSurface(view->getPositionInWindow() +
view->getSize(), {100, 100});

Examples:


_<AOverlappingSurface> ASurface::createOverlappingSurface(const std::function<AOptional<glm::ivec2>(unsigned)>& positionFactory, const glm::ivec2& size, bool closeOnClick = true)
Arguments
positionFactory
a function that return position where does the surface should be created. If the surface does not fit, the function is called again with previous arg+1.
size
size
closeOnClick
when true, overlapped surface is automatically closed when mouse clicked. It's usable for dropdown and context menus.
Returns
a new surface.

Create a surface used for context menus and combo boxes. Closure of the surface is controlled by closeOnClick param but can be closed manually by calling closeOverlappingSurface.

Examples:

current#


static ASurface* ASurface::current()
Returns
Current surface for current thread.

Examples:

examples/7guis/cells/src/Spreadsheet.h

7GUIs Cells — Spreadsheet processor (Excel).

        struct RangeIterator {
            const Spreadsheet* spreadsheet;
            formula::Range range;
            glm::uvec2 current;

            RangeIterator operator++() {
                current.x += 1;
                if (current.x <= range.to.x) {
                    return *this;

enqueueLayoutRoot#


void ASurface::enqueueLayoutRoot(AView& view)

Schedules view to be laid out on its own, without laying out the rest of the surface.

Called by AView::requestLayout of a view that is a layout boundary, i.e. a view whose geometry can't be affected by whatever happens inside it. Such a view is laid out by ASurface::applyPendingLayoutRoots before the next frame is drawn, instead of dragging the whole view hierarchy through a layout update.

forceUpdateCursor#


virtual void ASurface::forceUpdateCursor()

Updates cursor by triggering onPointerMove on the same position (mMousePos).

frameMillis#


virtual unsigned ASurface::frameMillis()

Returns previous frame's rendering duration in millis.

Returns previous frame's rendering duration in millis, including native rendering preparation and buffer swapping. The value does not include the elapsed time between frames.

The value is updated after native buffer swap.

getDpiRatio#


float ASurface::getDpiRatio()

Returns current dpi ratio

dpi ratio value is rounded to 0.25

getFps#


size_t ASurface::getFps()
Returns
Last captured FPS

FPS is captured every second

isPreventingClickOnPointerRelease#


bool ASurface::isPreventingClickOnPointerRelease()

iterateOverFocusChain#


template<aui::invocable<const _<AView> &> Callback >
void ASurface::iterateOverFocusChain(Callback&& callback)

Iterates over focus chain, from parent to child.

onDragEnter#


virtual bool ASurface::onDragEnter(const ADragNDrop::EnterEvent& event)

Called when the user holds a drag-n-drop object over the window.

Arguments
event
event data.
Returns
true, if the application accepts the contents of the event, false otherwise.

This event handler decides does the application accepts the supplied data. If true, the data supplied to the onDragDrop() method will be the same.

onDragLeave() method will be called even if the application rejects the event.

It's guaranteed that onDragDrop method will not be called when onDragEnter rejects the same data.

Examples:

examples/ui/views/src/ExampleWindow.h

Views Example — All-in-one views building example.

    ExampleWindow();

    void onDragDrop(const ADragNDrop::DropEvent& event) override;

    bool onDragEnter(const ADragNDrop::EnterEvent& event) override;

private:
    ADeque<_<AWindow>> mWindows;
    AAsyncHolder mAsync;
    _<IAudioPlayer> mWavAudio;

preventClickOnPointerRelease#


void ASurface::preventClickOnPointerRelease()

Prevents click action on upcoming pointer release.

Also disables hover and pressed animations.

Used by AScrollArea when it's scroll is triggered.

Calls AView::onClickPrevented() over focus chain.

profiling#


aui::lazy<Profiling>& ASurface::profiling()

Get profiling settings (mutable).

requestHideTouchscreenKeyboard#


void ASurface::requestHideTouchscreenKeyboard()

On a mobile touchscreen device, requests hiding system virtual keyboard.

requestShowTouchscreenKeyboard#


void ASurface::requestShowTouchscreenKeyboard()

On a mobile touchscreen device, requests system virtual keyboard.

setScalingParams#


void ASurface::setScalingParams(ScalingParams params)

Sets scaling params

Examples:

shouldDisplayHoverAnimations#


bool ASurface::shouldDisplayHoverAnimations()

Determines whether views should display hover animations.

Returns
false when any keyboard button is pressed