A bunch of minor bug fixes related to incorrect pixel density usage in different widget types. Optimized drainAsyncResourceMainThreadQueue to avoid in most common cases heap-allocating and to correctly call functions in the right UISceneNode context.

This commit is contained in:
Martín Lucas Golini
2026-09-30 02:01:33 -03:00
parent f8f5627f77
commit cd16932ba9
6 changed files with 69 additions and 15 deletions
+1 -1
View File
@@ -271,7 +271,7 @@ void UIListBox::setRowHeight() {
fontSize =
fontStyleConfig.getFont()->getFontHeight( fontStyleConfig.getFontCharacterSize() );
mRowHeight = PixelDensity::pxToDp( fontSize ) + PixelDensity::dpToPx( 4 );
mRowHeight = PixelDensity::pxToDp( fontSize ) + 4;
}
if ( tOldRowHeight != mRowHeight ) {
+1 -1
View File
@@ -12,7 +12,7 @@ UILoader* UILoader::New() {
UILoader::UILoader() :
UIWidget( "loader" ),
mRadius( 0 ),
mOutlineThickness( PixelDensity::dpToPx( 8 ) ),
mOutlineThickness( 8 ),
mColor( Color::White ),
mArcAngle( 0 ),
mArcStartAngle( 0 ),
+13 -7
View File
@@ -1,5 +1,6 @@
#include <algorithm>
#include <cstdlib>
#include <eepp/core/small_vector.hpp>
#include <eepp/core/string.hpp>
#include <eepp/graphics/fontservice.hpp>
#include <eepp/graphics/fonttruetype.hpp>
@@ -57,12 +58,13 @@ struct PendingAsyncResourceMainThread {
enum class AsyncResourceMainThreadQueueState : Uint8 { Closed, Open, Closing };
std::mutex sAsyncResourceMainThreadMutex;
std::vector<PendingAsyncResourceMainThread> sAsyncResourceMainThreadQueue;
using AsyncResourceMainThreadQueue = SmallVector<PendingAsyncResourceMainThread, 4>;
AsyncResourceMainThreadQueue sAsyncResourceMainThreadQueue;
std::atomic<AsyncResourceMainThreadQueueState> sAsyncResourceMainThreadQueueState{
AsyncResourceMainThreadQueueState::Closed };
void drainAsyncResourceMainThreadQueue() {
std::vector<PendingAsyncResourceMainThread> pending;
AsyncResourceMainThreadQueue pending;
{
std::lock_guard<std::mutex> lock( sAsyncResourceMainThreadMutex );
if ( sAsyncResourceMainThreadQueueState.load( std::memory_order_relaxed ) !=
@@ -71,7 +73,7 @@ void drainAsyncResourceMainThreadQueue() {
pending.swap( sAsyncResourceMainThreadQueue );
}
std::vector<PendingAsyncResourceMainThread> delayed;
AsyncResourceMainThreadQueue delayed;
for ( auto& item : pending ) {
if ( !UISceneNode::isAsyncResourceLoadCurrent( item.resourceState, item.generation ) )
continue;
@@ -82,8 +84,10 @@ void drainAsyncResourceMainThreadQueue() {
}
UISceneNode* owner = item.resourceState->owner.load( std::memory_order_acquire );
if ( owner && item.func )
if ( owner && item.func ) {
auto context = owner->makeCurrent();
item.func( owner );
}
}
if ( !delayed.empty() ) {
@@ -2323,8 +2327,10 @@ void UISceneNode::runAsyncResourceOnMainThread(
if ( isAsyncResourceLoadCurrent( resourceState, generation ) && Engine::isMainThread() &&
delay <= Time::Zero ) {
UISceneNode* owner = resourceState->owner.load( std::memory_order_acquire );
if ( owner )
if ( owner ) {
auto context = owner->makeCurrent();
func( owner );
}
return;
}
@@ -2342,7 +2348,7 @@ void UISceneNode::runAsyncResourceOnMainThread(
}
void UISceneNode::openAsyncResourceMainThreadQueue() {
std::vector<PendingAsyncResourceMainThread> stale;
AsyncResourceMainThreadQueue stale;
{
std::lock_guard<std::mutex> lock( sAsyncResourceMainThreadMutex );
stale.swap( sAsyncResourceMainThreadQueue );
@@ -2358,7 +2364,7 @@ void UISceneNode::beginAsyncResourceMainThreadQueueShutdown() {
}
void UISceneNode::finishAsyncResourceMainThreadQueueShutdown() {
std::vector<PendingAsyncResourceMainThread> pending;
AsyncResourceMainThreadQueue pending;
{
std::lock_guard<std::mutex> lock( sAsyncResourceMainThreadMutex );
sAsyncResourceMainThreadQueueState.store( AsyncResourceMainThreadQueueState::Closed,
+1 -1
View File
@@ -20,7 +20,7 @@ UIViewPager::UIViewPager() :
mOrientation( UIOrientation::Horizontal ),
mDragging( false ),
mLocked( false ),
mDragResistance( PixelDensity::dpToPx( 8 ) ),
mDragResistance( 8 ),
mInitialDisplacement( 0 ),
mDisplacement( 0 ),
mChangePagePercent( 0.33f ),
+5 -5
View File
@@ -1011,7 +1011,7 @@ UIWidget* UIWidget::setPaddingBottom( const Float& paddingBottom ) {
UIWidget* UIWidget::setPaddingPixels( const Rectf& padding ) {
if ( padding != mPadding ) {
mPaddingPx = padding;
mPadding = PixelDensity::pxToDp( mPadding ).ceil();
mPadding = PixelDensity::pxToDp( mPaddingPx ).ceil();
onAutoSize();
onPaddingChange();
notifyLayoutAttrChange( LayoutInvalidation::Self );
@@ -1023,7 +1023,7 @@ UIWidget* UIWidget::setPaddingPixels( const Rectf& padding ) {
UIWidget* UIWidget::setPaddingPixelsLeft( const Float& paddingLeft ) {
if ( paddingLeft != mPadding.Left ) {
mPaddingPx.Left = paddingLeft;
mPadding.Left = eeceil( PixelDensity::pxToDp( mPadding.Left ) );
mPadding.Left = eeceil( PixelDensity::pxToDp( mPaddingPx.Left ) );
onAutoSize();
onPaddingChange();
notifyLayoutAttrChange( LayoutInvalidation::Self );
@@ -1035,7 +1035,7 @@ UIWidget* UIWidget::setPaddingPixelsLeft( const Float& paddingLeft ) {
UIWidget* UIWidget::setPaddingPixelsRight( const Float& paddingRight ) {
if ( paddingRight != mPadding.Right ) {
mPaddingPx.Right = paddingRight;
mPadding.Right = eeceil( PixelDensity::pxToDp( mPadding.Right ) );
mPadding.Right = eeceil( PixelDensity::pxToDp( mPaddingPx.Right ) );
onAutoSize();
onPaddingChange();
notifyLayoutAttrChange( LayoutInvalidation::Self );
@@ -1047,7 +1047,7 @@ UIWidget* UIWidget::setPaddingPixelsRight( const Float& paddingRight ) {
UIWidget* UIWidget::setPaddingPixelsTop( const Float& paddingTop ) {
if ( paddingTop != mPadding.Top ) {
mPaddingPx.Top = paddingTop;
mPadding.Top = eeceil( PixelDensity::pxToDp( mPadding.Top ) );
mPadding.Top = eeceil( PixelDensity::pxToDp( mPaddingPx.Top ) );
onAutoSize();
onPaddingChange();
notifyLayoutAttrChange( LayoutInvalidation::Self );
@@ -1059,7 +1059,7 @@ UIWidget* UIWidget::setPaddingPixelsTop( const Float& paddingTop ) {
UIWidget* UIWidget::setPaddingPixelsBottom( const Float& paddingBottom ) {
if ( paddingBottom != mPadding.Bottom ) {
mPaddingPx.Bottom = paddingBottom;
mPadding.Bottom = eeceil( PixelDensity::pxToDp( mPadding.Bottom ) );
mPadding.Bottom = eeceil( PixelDensity::pxToDp( mPaddingPx.Bottom ) );
onAutoSize();
onPaddingChange();
notifyLayoutAttrChange( LayoutInvalidation::Self );
@@ -21,6 +21,7 @@
#include <eepp/window/engine.hpp>
#include <eepp/window/input.hpp>
#include <eepp/window/runtime.hpp>
#include <thread>
using namespace EE;
using namespace EE::Graphics;
@@ -134,6 +135,53 @@ UTEST( UISceneNode, ScopedContextBindsNodesAndRestoresNestedScene ) {
eeDelete( sceneA );
}
UTEST( UISceneNode, AsyncResourceCallbacksBindOwnerSceneAndRestorePreviousScene ) {
auto* engine = Engine::instance();
auto* window = engine->getCurrentWindow();
if ( !window ) {
window = engine->createWindow( WindowSettings( 320, 240, "Async Resource Context Test",
WindowStyle::Default, WindowBackend::Default,
32, {}, 1, false, true ),
ContextSettings( false, 0, 0, GLv_default, true, false ) );
}
auto* sceneA = UISceneNode::New( window );
auto* sceneB = UISceneNode::New( window );
auto* sceneManager = SceneManager::instance();
sceneManager->add( sceneA );
sceneManager->add( sceneB );
sceneManager->setCurrentUISceneNode( sceneA );
auto state = sceneB->getAsyncResourceLoadState();
const Uint64 generation = state->generation.load( std::memory_order_acquire );
bool immediateBound = false;
bool queuedBound = false;
{
auto context = sceneA->makeCurrent();
UISceneNode::runAsyncResourceOnMainThread( state, generation, [&]( UISceneNode* owner ) {
immediateBound = owner == sceneB && sceneManager->getUISceneNode() == sceneB;
} );
EXPECT_EQ( sceneManager->getUISceneNode(), sceneA );
std::thread producer( [&] {
UISceneNode::runAsyncResourceOnMainThread(
state, generation, [&]( UISceneNode* owner ) {
queuedBound = owner == sceneB && sceneManager->getUISceneNode() == sceneB;
} );
} );
producer.join();
sceneA->update( Time::Zero );
EXPECT_EQ( sceneManager->getUISceneNode(), sceneA );
}
EXPECT_TRUE( immediateBound );
EXPECT_TRUE( queuedBound );
sceneManager->remove( sceneB );
sceneManager->remove( sceneA );
eeDelete( sceneB );
eeDelete( sceneA );
}
class TestUIApplication : public UIApplication {
public:
using UIApplication::UIApplication;