AUI Framework  master
Cross-platform module-based framework for developing C++20 desktop applications
AWindowBase.h
1/*
2 * AUI Framework - Declarative UI toolkit for modern C++20
3 * Copyright (C) 2020-2024 Alex2772 and Contributors
4 *
5 * SPDX-License-Identifier: MPL-2.0
6 *
7 * This Source Code Form is subject to the terms of the Mozilla Public
8 * License, v. 2.0. If a copy of the MPL was not distributed with this
9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 */
11
12//
13// Created by alex2 on 6/9/2021.
14//
15
16#pragma once
17
18#include <AUI/View/AViewContainer.h>
19#include "AUI/Performance/APerformanceFrame.h"
20#include "AUI/Performance/APerformanceSection.h"
21#include "AWindowManager.h"
22#include "AOverlappingSurface.h"
23#include "ADragNDrop.h"
24#include "AUI/Util/ATouchScroller.h"
25#include "ATouchscreenKeyboardPolicy.h"
26#include <chrono>
27#include <optional>
28
29namespace testing {
30 class UITest;
31}
32
33class API_AUI_VIEWS AWindowBase: public AViewContainer {
34 friend class SoftwareRenderer;
35 friend class testing::UITest;
36 friend struct IRenderingContext::Init;
37
38public:
40
42
48 struct Profiling {
53
57 bool highlightRedrawRequests = false;
58
63 bool renderToTextureDecay = false;
64
69 bool breakpointOnMarkMinContentSizeInvalid = false;
70 };
71
72
87 virtual void blockUserInput(bool blockUserInput = true);
88
89 virtual ~AWindowBase();
90
91
101 void preventClickOnPointerRelease();
102
106 [[nodiscard]]
107 bool isPreventingClickOnPointerRelease() const noexcept {
108 return mPreventClickOnPointerRelease.valueOr(false);
109 }
110
114 template<aui::invocable<const _<AView>&> Callback>
115 void iterateOverFocusChain(Callback&& callback) {
116 for (auto view = mFocusedView.lock(); view;) {
117 callback(view);
118
119 auto container = _cast<AViewContainer>(view);
120 if (!container) return;
121 view = container->focusChainTarget();
122 }
123 }
124
133 [[nodiscard]]
134 virtual unsigned frameMillis() const noexcept = 0;
135
136 static AWindowManager& getWindowManager() {
137 return *getWindowManagerImpl();
138 }
139 template<typename WindowManager, typename... Args>
140 static void setWindowManager(Args&&... args) {
141 destroyWindowManager(); // destroys previous window manager so IEventLoop::Handle sets window manager to the
142 // previous one BEFORE the new window manager is set
143 getWindowManagerImpl() = std::make_unique<WindowManager>(std::forward<Args>(args)...);
144 }
145 static void destroyWindowManager() {
146 getWindowManagerImpl() = nullptr;
147 }
148
149 const _unique<IRenderingContext>& getRenderingContext() const {
150 return mRenderingContext;
151 }
152
153 [[nodiscard]]
154 BeforeFrameQueue& beforeFrameQueue() noexcept {
155 return mBeforeFrameQueue;
156 }
157
158 void updateDpi();
159
166 {
167 return mDpiRatio;
168 }
169
170 _<AView> getFocusedView() const
171 {
172 return mFocusedView.lock();
173 }
174
175 void setFocusedView(const _<AView>& view);
176 void updateFocusChain();
177 void onPointerPressed(const APointerPressedEvent& event) override;
178
179 void onPointerMove(glm::vec2 pos, const APointerMoveEvent& event) override;
180
181 void closeOverlappingSurfacesOnClick();
182
183 bool isFocused() const {
184 return mIsFocused;
185 }
186
187 [[nodiscard]]
188 const glm::ivec2& getMousePos() const {
189 return mMousePos;
190 }
191
192 void onKeyDown(AInput::Key key) override;
193
194
195 virtual void focusNextView();
196 virtual void flagRedraw();
197
198 void makeCurrent() {
199 currentWindowStorage() = this;
200 }
201
230 const glm::ivec2& size,
231 bool closeOnClick = true) {
232 return createOverlappingSurface([&](unsigned attempt) -> AOptional<glm::ivec2> {
233 switch (attempt) {
234 case 0: return position;
235 case 1: return glm::clamp(position, {0, 0}, {getSize() - size});
236 default: return std::nullopt;
237 }
238 }, size, closeOnClick);
239 }
240
251 _<AOverlappingSurface> createOverlappingSurface(const std::function<AOptional<glm::ivec2>(unsigned)>& positionFactory,
252 const glm::ivec2& size,
253 bool closeOnClick = true) {
254 glm::ivec2 position = {0, 0};
255 auto maxPos = getSize() - size;
256 for (unsigned index = 0; ; ++index) {
257 auto optionalPosition = positionFactory(index);
258 if (optionalPosition) {
259 position = *optionalPosition;
260
261 if (position.x >= 0 && position.y >= 0 && glm::all(glm::lessThan(position, maxPos))) {
262 break;
263 }
264 } else {
265 break;
266 }
267 }
268
269 auto tmp = createOverlappingSurfaceImpl(position, size);
270 tmp->mParentWindow = this;
271 tmp->mCloseOnClick = closeOnClick;
272 mOverlappingSurfaces << tmp;
273 return tmp;
274 }
275 void closeOverlappingSurface(AOverlappingSurface* surface) {
276 if (mOverlappingSurfaces.erase(aui::ptr::fake(surface)) > 0) {
277 closeOverlappingSurfaceImpl(surface);
278 }
279 }
280
281 void onFocusLost() override;
282 void render(ARenderContext context) override;
283 void applyGeometryToChildren() override;
284 void onPointerReleased(const APointerReleasedEvent& event) override;
285
298 virtual bool onDragEnter(const ADragNDrop::EnterEvent& event);
299 virtual void onDragLeave();
300 virtual void onDragDrop(const ADragNDrop::DropEvent& event);
301
305 void requestShowTouchscreenKeyboard();
306
310 void requestHideTouchscreenKeyboard();
311
316 bool shouldDisplayHoverAnimations() const;
317
318 void onScroll(const AScrollEvent& event) override;
319
323 virtual void forceUpdateCursor();
324
325 bool onGesture(const glm::ivec2& origin, const AGestureEvent& event) override;
326
330 static constexpr std::chrono::milliseconds DOUBLECLICK_MAX_DURATION = std::chrono::milliseconds(500);
331
336 size_t getFps() {
337 return mLastCapturedFps;
338 }
339
340 void setTouchscreenKeyboardPolicy(ATouchscreenKeyboardPolicy policy) noexcept {
341 mKeyboardPolicy = policy;
342 }
343
348 float scalingFactor = 1.f;
353 AOptional<glm::uvec2> minimalWindowSizeDp = std::nullopt;
354 };
355
360 void setScalingParams(ScalingParams params);
361
366 return mProfiling;
367 }
368
369 void markMinContentSizeInvalid() override;
370
371signals:
372 emits<> dpiChanged;
374 emits<AInput::Key> keyDown;
375 emits<> redrawn;
376
381
382
387
388#if AUI_PROFILING
389 emits<APerformanceSection::Datas> performanceFrameComplete;
390#endif
391
392protected:
393 bool mIsFocused = true;
394
399
403 bool mForceUpdateCursorGuard = false;
404
405 bool mPerformDoubleClickOnPointerRelease = false;
406
407 std::chrono::milliseconds mLastButtonPressedTime = std::chrono::milliseconds::zero();
408 AOptional<APointerIndex> mLastButtonPressed;
409 glm::vec2 mLastPosition = {0, 0};
410
411 _unique<IRenderingContext> mRenderingContext;
412
413 static AWindowBase*& currentWindowStorage();
414
418 virtual _<AOverlappingSurface> createOverlappingSurfaceImpl(const glm::ivec2& position, const glm::ivec2& size) = 0;
419 virtual void closeOverlappingSurfaceImpl(AOverlappingSurface* surface) = 0;
420
421 virtual void createDevtoolsWindow();
422
423 static _unique<AWindowManager>& getWindowManagerImpl();
424
425 virtual float fetchDpiFromSystem() const;
426
427 virtual void showTouchscreenKeyboardImpl();
428 virtual void hideTouchscreenKeyboardImpl();
429
430 void markPixelDataInvalid(ARect<int> invalidArea) override;
431
432private:
433 void processTouchscreenKeyboardRequest();
434
435 _weak<AView> mFocusedView;
436 Profiling mProfiling{};
437 float mDpiRatio = 1.f;
438 ScalingParams mScalingParams;
439
440 BeforeFrameQueue mBeforeFrameQueue;
441
442 ATouchscreenKeyboardPolicy mKeyboardPolicy = ATouchscreenKeyboardPolicy::SHOWN_IF_NEEDED;
443
444 enum class KeyboardRequest {
445 NO_OP,
446 SHOW,
447 HIDE
448 };
449
450 KeyboardRequest mKeyboardRequestedState = KeyboardRequest::NO_OP;
451
452 glm::ivec2 mMousePos = {0, 0};
453 ASet<_<AOverlappingSurface>> mOverlappingSurfaces;
454
455 struct Scroll {
456 APointerIndex pointer;
457 ATouchScroller scroller;
458 };
459
463 ASmallVector<Scroll, 10 /* typical max number of fingers */> mScrolls;
464
465 std::chrono::time_point<std::chrono::high_resolution_clock> mLastTimeFpsCaptured = std::chrono::high_resolution_clock::now();
466 size_t mFpsCounter = 0;
467 size_t mLastCapturedFps = 0;
468
469#if AUI_SHOW_TOUCHES
470 struct ShowTouches {
471 glm::vec2 press;
472 AVector<glm::vec2> moves;
473 AOptional<glm::vec2> release;
474 };
476#endif
477};
478
479
486#define AUI_ASSERT_UI_THREAD_ONLY() { AUI_ASSERTX((AWindow::current() ? AThread::current() == AWindow::current()->getThread() : AThread::current() == getThread()), "this method should be used in ui thread only."); }
487
494#define AUI_ASSERT_WORKER_THREAD_ONLY() { AUI_ASSERTX(AThread::current() != AWindow::current()->getThread(), "this method should be used in worker thread only."); }
495
A std::map with AUI extensions.
Definition: AMap.h:218
Utility wrapper implementing the stack-allocated (fast) optional idiom.
Definition: AOptional.h:32
Definition: AOverlappingSurface.h:19
Wrapper class that stores either mouse button index or finger index.
Definition: APointerIndex.h:21
A std::set with AUI extensions.
Definition: ASet.h:25
Vector-like container consisting of few elements on stack and switches to dynamic allocation vector i...
Definition: ASmallVector.h:34
Utility object that helps with touchscreen scroll events.
Definition: ATouchScroller.h:29
A std::vector with AUI extensions.
Definition: AVector.h:38
void onPointerPressed(const APointerPressedEvent &event) override
Called on pointer (mouse) released event.
Definition: AViewContainerBase.cpp:287
bool onGesture(const glm::ivec2 &origin, const AGestureEvent &event) override
Definition: AViewContainerBase.cpp:547
void onPointerMove(glm::vec2 pos, const APointerMoveEvent &event) override
Handles pointer hover events.
Definition: AViewContainerBase.cpp:242
void markPixelDataInvalid(ARect< int > invalidArea) override
A view requests to redraw it and passes it's coords relative to this.
Definition: AViewContainerBase.cpp:641
void onPointerReleased(const APointerReleasedEvent &event) override
Called on pointer (mouse) released event.
Definition: AViewContainerBase.cpp:327
void onScroll(const AScrollEvent &event) override
Definition: AViewContainerBase.cpp:359
void render(ARenderContext context) override
Draws this AView. Noone should call this function except rendering routine.
Definition: AViewContainerBase.cpp:233
A trivial modifiable view that represents a set of views.
Definition: AViewContainer.h:33
glm::ivec2 getSize() const noexcept
Size, including content area, border and padding.
Definition: AView.h:370
Definition: AWindowBase.h:33
float getDpiRatio()
Returns current dpi ratio.
Definition: AWindowBase.h:165
bool isPreventingClickOnPointerRelease() const noexcept
Definition: AWindowBase.h:107
AOptional< bool > mPreventClickOnPointerRelease
Definition: AWindowBase.h:398
virtual _< AOverlappingSurface > createOverlappingSurfaceImpl(const glm::ivec2 &position, const glm::ivec2 &size)=0
void iterateOverFocusChain(Callback &&callback)
Iterates over focus chain, from parent to child.
Definition: AWindowBase.h:115
_< AOverlappingSurface > createOverlappingSurface(const glm::ivec2 &position, const glm::ivec2 &size, bool closeOnClick=true)
Definition: AWindowBase.h:229
virtual unsigned frameMillis() const noexcept=0
Returns previous frame's rendering duration in millis.
emits touchscreenKeyboardHidden
On touch screen keyboard hide.
Definition: AWindowBase.h:386
size_t getFps()
Definition: AWindowBase.h:336
_< AOverlappingSurface > createOverlappingSurface(const std::function< AOptional< glm::ivec2 >(unsigned)> &positionFactory, const glm::ivec2 &size, bool closeOnClick=true)
Definition: AWindowBase.h:251
emits touchscreenKeyboardShown
On touch screen keyboard show.
Definition: AWindowBase.h:380
Profiling & profiling()
Get profiling settings (mutable).
Definition: AWindowBase.h:365
Definition: AWindowManager.h:23
Definition: SoftwareRenderer.h:19
An std::weak_ptr with AUI extensions.
Definition: SharedPtrTypes.h:177
Definition: UITestCase.h:26
API_AUI_CORE const ACommandLineArgs & args() noexcept
Definition: OSAndroid.cpp:29
Definition: ADragNDrop.h:67
Definition: ADragNDrop.h:62
Pointing method move event.
Definition: APointerMoveEvent.h:21
Pointing method press event.
Definition: APointerPressedEvent.h:21
Pointing method press event.
Definition: APointerReleasedEvent.h:19
Axis aligned 2D rectangle.
Definition: ARect.h:24
Render context passed to AView::render.
Definition: ARenderContext.h:43
Pointing method scroll event.
Definition: AScrollEvent.h:20
Profiling (debugging) settings for this window.
Definition: AWindowBase.h:48
_weak< AView > highlightView
View to highlight.
Definition: AWindowBase.h:52
Definition: AWindowBase.h:344
Definition: IRenderingContext.h:38
Definition: MouseMove.h:16
An std::weak_ptr with AUI extensions.
Definition: SharedPtrTypes.h:51
static _< T > fake(T *raw)
Definition: SharedPtrTypes.h:376