mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-01 18:50:16 +03:00
Fix CSS pointer cursor handling on hovered widgets
Map the standard CSS pointer value to the hand cursor and retain the computed cursor in each UIWidget instead of mutating the scene during style application. Apply the retained cursor when a widget becomes the hover target, restore the arrow when leaving the UI, and make cursor inheritance available to descendants such as inline SVG elements. Store cursor state in an existing UIWidget padding gap and centralize cursor serialization in Cursor::toName(). Add regressions for pointer parsing, cursor serialization, inheritance, and the SS64 search button SVG.
This commit is contained in:
@@ -212,7 +212,7 @@ void StyleSheetSpecification::registerDefaultProperties() {
|
||||
.setType( PropertyType::NumberLength )
|
||||
.setRelativeTarget( PropertyRelativeTarget::ContainingBlockHeight );
|
||||
registerProperty( "opacity", "" ).setType( PropertyType::NumberFloat );
|
||||
registerProperty( "cursor", "arrow" );
|
||||
registerProperty( "cursor", "arrow", true );
|
||||
registerProperty( "text", "" ).setType( PropertyType::String );
|
||||
registerProperty( "text-transform", "", true ).setType( PropertyType::String );
|
||||
registerProperty( "color", "", true )
|
||||
|
||||
@@ -509,7 +509,10 @@ Uint32 UIWidget::onMouseOver( const Vector2i& position, const Uint32& flags ) {
|
||||
}
|
||||
}
|
||||
|
||||
return UINode::onMouseOver( position, flags );
|
||||
Uint32 result = UINode::onMouseOver( position, flags );
|
||||
if ( mSceneNode )
|
||||
mSceneNode->setCursor( getCursor() );
|
||||
return result;
|
||||
}
|
||||
|
||||
Uint32 UIWidget::onMouseLeave( const Vector2i& Pos, const Uint32& Flags ) {
|
||||
@@ -519,6 +522,8 @@ Uint32 UIWidget::onMouseLeave( const Vector2i& Pos, const Uint32& Flags ) {
|
||||
NULL != mTooltip && !mTooltip->dontAutoHideOnMouseMove() ) {
|
||||
mTooltip->hide();
|
||||
}
|
||||
if ( NULL != eventDispatcher && eventDispatcher->getMouseOverNode() == nullptr && mSceneNode )
|
||||
mSceneNode->setCursor( Cursor::Arrow );
|
||||
|
||||
return UINode::onMouseLeave( Pos, Flags );
|
||||
}
|
||||
@@ -1691,6 +1696,10 @@ std::vector<UIWidget*> UIWidget::querySelectorAll( const std::string& selector )
|
||||
return querySelectorAll( CSS::StyleSheetSelector( selector ) );
|
||||
}
|
||||
|
||||
Cursor::Type UIWidget::getCursor() const {
|
||||
return static_cast<Cursor::Type>( mCursor );
|
||||
}
|
||||
|
||||
std::vector<PropertyId> UIWidget::getPropertiesImplemented() const {
|
||||
return { PropertyId::X,
|
||||
PropertyId::Y,
|
||||
@@ -1832,7 +1841,7 @@ std::string UIWidget::getPropertyString( const PropertyDefinition* propertyDef,
|
||||
case PropertyId::Opacity:
|
||||
return String::fromFloat( getAlpha() / 255.f );
|
||||
case PropertyId::Cursor:
|
||||
return "arrow";
|
||||
return Cursor::toName( getCursor() );
|
||||
case PropertyId::Visible:
|
||||
return isVisible() ? "true" : "false";
|
||||
case PropertyId::Enabled:
|
||||
@@ -2410,7 +2419,10 @@ bool UIWidget::applyProperty( const StyleSheetProperty& attribute ) {
|
||||
break;
|
||||
}
|
||||
case PropertyId::Cursor:
|
||||
mSceneNode->setCursor( Cursor::fromName( attribute.getValue() ) );
|
||||
mCursor = static_cast<Uint8>( Cursor::fromName( attribute.getValue() ) );
|
||||
if ( mSceneNode && getEventDispatcher() &&
|
||||
getEventDispatcher()->getMouseOverNode() == this )
|
||||
mSceneNode->setCursor( getCursor() );
|
||||
break;
|
||||
case PropertyId::BackgroundPositionX:
|
||||
setBackgroundPositionX( attribute.value(), attribute.getIndex() );
|
||||
|
||||
@@ -88,6 +88,37 @@ Cursor::Type Cursor::fromName( std::string name ) {
|
||||
return Arrow;
|
||||
}
|
||||
|
||||
const char* Cursor::toName( Cursor::Type cursor ) {
|
||||
switch ( cursor ) {
|
||||
case Hand:
|
||||
return "hand";
|
||||
case IBeam:
|
||||
return "ibeam";
|
||||
case Wait:
|
||||
return "wait";
|
||||
case Crosshair:
|
||||
return "crosshair";
|
||||
case WaitArrow:
|
||||
return "waitarrow";
|
||||
case SizeNWSE:
|
||||
return "sizenwse";
|
||||
case SizeNESW:
|
||||
return "sizenesw";
|
||||
case SizeWE:
|
||||
return "sizewe";
|
||||
case SizeNS:
|
||||
return "sizens";
|
||||
case SizeAll:
|
||||
return "sizeall";
|
||||
case NoCursor:
|
||||
return "nocursor";
|
||||
case Arrow:
|
||||
case CursorCount:
|
||||
return "arrow";
|
||||
}
|
||||
return "arrow";
|
||||
}
|
||||
|
||||
const String::HashType& Cursor::getId() const {
|
||||
return mId;
|
||||
}
|
||||
|
||||
@@ -650,6 +650,8 @@ UTEST( UIHTMLFloat, ss64BlockAnchorsAndSvgAtPixelDensity2 ) {
|
||||
ASSERT_TRUE( input != nullptr );
|
||||
ASSERT_TRUE( searchButton != nullptr );
|
||||
ASSERT_TRUE( svg != nullptr );
|
||||
EXPECT_EQ( searchButton->getCursor(), Cursor::Hand );
|
||||
EXPECT_EQ( svg->getCursor(), Cursor::Hand );
|
||||
EXPECT_NEAR( input->getPixelsSize().getHeight(), 74.5f, 1.f );
|
||||
EXPECT_NEAR( searchButton->getPixelsSize().getHeight(), 69.f, 1.f );
|
||||
EXPECT_LE( searchButton->getPixelsPosition().y + searchButton->getPixelsSize().getHeight(),
|
||||
|
||||
@@ -23,6 +23,8 @@ using namespace EE::UI;
|
||||
UTEST( UISceneNode, CssPointerCursorUsesHandCursor ) {
|
||||
EXPECT_EQ( Cursor::fromName( "pointer" ), Cursor::Hand );
|
||||
EXPECT_EQ( Cursor::fromName( "POINTER" ), Cursor::Hand );
|
||||
EXPECT_STREQ( Cursor::toName( Cursor::Hand ), "hand" );
|
||||
EXPECT_STREQ( Cursor::toName( Cursor::Arrow ), "arrow" );
|
||||
}
|
||||
|
||||
static UISceneNode* init_test_scene_node() {
|
||||
|
||||
Reference in New Issue
Block a user