Skip to content

Conversation

MiaKoring
Copy link
Contributor

@MiaKoring MiaKoring commented Sep 7, 2025

This PR introduces a new .onHover modifier to Views.
Related Issue: #211
Added in this PR:

  • Extension View

    • onHover { Bool in }
  • protocol AppBackend

    • createHoverTarget
    • updateHoverTarget
    • Default implementation for Backends without implementation
  • Backend Support

    • AppKitBackend
    • UIKitBackend
    • GtkBackend
    • WinUIBackend
  • Other changes:

    • left & right NSClickGestureRecognizer now get set to nil in NSCustomTapGestureTarget when corresponding function gets set to nil
    • UISlider now Supports macCatalyst (added through compilerflag)
    • Added HoverExample
    • (format_and_lint.sh and generate.sh automatic changes)

HoverExample erfolgreich getestet auf:
macOS 26 (AppKitBackend, GtkBackend, UIKitBackend (macCatalyst))
iPadOS 26 (UIKitBackend)
Windows 11 (WinUI Backend)
Fedora 44 (GtkBackend)

Notes:
Gtk versions below 4.20.0 may encounter compiling problems. I don’t know why or what caused it, I only used the generate script, but on 4.18.6 on Fedora 42 I got this Error:

/home/mia/Documents/swift-cross-ui/Sources/Gtk/Generated/PadActionType.swift:28:6: error: cannot find 'GTK_PAD_ACTION_DIAL' in scope
26 | case GTK_PAD_ACTION_STRIP:
27 |     self = .strip
28 | case GTK_PAD_ACTION_DIAL:
   |      `- error: cannot find 'GTK_PAD_ACTION_DIAL' in scope
29 |     self = .dial
30 |             default:

I checked and it should’ve been available since 4.0 https://docs.gtk.org/gtk4/enum.PadActionType.html
Maybe someone knows how to fix it and maybe it was just a local issue.

I made the weird Array-in-foreach-decision, since closed ranges didn't seem to be supported yet.

test.sh output

   Test Suite 'All tests' started at 2025-09-08 00:03:46.577.
Test Suite 'swift-cross-uiPackageTests.xctest' started at 2025-09-08 00:03:46.584.
Test Suite 'SwiftCrossUITests' started at 2025-09-08 00:03:46.584.
Test Case '-[SwiftCrossUITests.SwiftCrossUITests testBasicLayout]' started.
/Users/miakoring/Documents/Fork/swift-cross-ui/Tests/SwiftCrossUITests/SwiftCrossUITests.swift:203: error: -[SwiftCrossUITests.SwiftCrossUITests testBasicLayout] : XCTAssertEqual failed: ("ViewSize(size: SIMD2<Int>(102, 104), idealSize: SIMD2<Int>(102, 104), idealWidthForProposedHeight: 102, idealHeightForProposedWidth: 104, minimumWidth: 102, minimumHeight: 104, maximumWidth: 102.0, maximumHeight: 104.0, participateInStackLayoutsWhenEmpty: true)") is not equal to ("ViewSize(size: SIMD2<Int>(92, 96), idealSize: SIMD2<Int>(92, 96), idealWidthForProposedHeight: 92, idealHeightForProposedWidth: 96, minimumWidth: 92, minimumHeight: 96, maximumWidth: 92.0, maximumHeight: 96.0, participateInStackLayoutsWhenEmpty: true)") - View update result mismatch
Test Case '-[SwiftCrossUITests.SwiftCrossUITests testBasicLayout]' failed (0.204 seconds).
Test Case '-[SwiftCrossUITests.SwiftCrossUITests testCodableNavigationPath]' started.
Test Case '-[SwiftCrossUITests.SwiftCrossUITests testCodableNavigationPath]' passed (0.001 seconds).
Test Case '-[SwiftCrossUITests.SwiftCrossUITests testStateObservation]' started.
Test Case '-[SwiftCrossUITests.SwiftCrossUITests testStateObservation]' passed (0.000 seconds).
Test Case '-[SwiftCrossUITests.SwiftCrossUITests testThrottledStateObservation]' started.
Test Case '-[SwiftCrossUITests.SwiftCrossUITests testThrottledStateObservation]' passed (0.225 seconds).
Test Suite 'SwiftCrossUITests' failed at 2025-09-08 00:03:47.014.
	 Executed 4 tests, with 1 failure (0 unexpected) in 0.430 (0.431) seconds
Test Suite 'swift-cross-uiPackageTests.xctest' failed at 2025-09-08 00:03:47.014.
	 Executed 4 tests, with 1 failure (0 unexpected) in 0.430 (0.431) seconds
Test Suite 'All tests' failed at 2025-09-08 00:03:47.014.
	 Executed 4 tests, with 1 failure (0 unexpected) in 0.430 (0.437) seconds
􀟈  Test run started.
􀄵  Testing Library Version: 1084
􀄵  Target Platform: arm64e-apple-macos14.0
􁁛  Test run with 0 tests in 0 suites passed after 0.001 seconds.

Added:
- onHover(_ action: (Bool) -> Void) View Extension
- OnHoverModifier TypeSafeView
- createHoverTarget(wrapping: Widget) -> Widget to AppBackend Protocol
- updateHoverTarget(_: Widget, environment: EnvironmentValues, action: (Bool) -> Void) to AppBackend Protocol
- corresponding default implementations
- AppKitBackend hover implementation
   - createHoverTarget implementation
   - updateHoverTarget implementation
   - NSCustomHoverTarget (NSView notifying about hovers)
- HoverExample

Fixed:
- AppKitBackend
   - fixed reference removing for NSClickGestureRecognizer in NSCustomTapGestureTarget
…ming fixes in AppKitBackend

- tapGestureRecognizer and longPressGestureRecognizer now get removed if their corresponding handler is set to nil.
- Added Hoverable Widget
- Added hovertarget creation & update functions
- added macCalatalyst as compatible for UISlider since it supports it
…ming fixes in AppKitBackend

- tapGestureRecognizer and longPressGestureRecognizer now get removed if their corresponding handler is set to nil.
- Added Hoverable Widget
- Added hovertarget creation & update functions
- added macCalatalyst as compatible for UISlider since it supports it
Copy link
Owner

@stackotter stackotter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! This will be quite useful for making more interactive apps. I've just requested a few changes around some implementation details but overall your approach to implementing this modifier was great.

@stackotter
Copy link
Owner

I checked and it should’ve been available since 4.0 https://docs.gtk.org/gtk4/enum.PadActionType.html
Maybe someone knows how to fix it and maybe it was just a local issue.

Gtk can be pretty weird about availability information. I think the best we can do is add a hardcoded check to filter out the enum case in GtkCodeGen.generateEnum. Make sure to leave a comment explaining that the check exists due to incorrect Gtk availability info for that particular enum case.

@stackotter
Copy link
Owner

That's interesting that testBasicLayout fails on your machine. It should be unrelated to your PR, so ignore that for now. I'll have to look into why it's happening at some point.

# Conflicts:
#	Sources/GtkCodeGen/GtkCodeGen.swift
@MiaKoring
Copy link
Contributor Author

MiaKoring commented Sep 15, 2025

I can’t test wether the linux compile bug is fixed because I don’t have a vm with older gtk atm. But I don’t see it in the generated code anymore. hopefully the build will now succeed

on WinUIBackend the explicit frame adjustments were indeed not necessary

@stackotter
Copy link
Owner

The PR froze safari for a few seconds when I tried to view the new changes because there are 266 changed files 😅 I think running ./format_and_lint.sh should fix that

@MiaKoring
Copy link
Contributor Author

didn’t help did it?

Copy link
Owner

@stackotter stackotter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just two small changes to make, other than that everything looks ready to merge

added both "GtkPadActionDial" and "PadActionDial" because I couldn't find a definitive answer what its called
added both "GtkPadActionDial" and "PadActionDial" because I couldn't find a definitive answer what its called

# Conflicts:
#	Sources/GtkCodeGen/GtkCodeGen.swift
@MiaKoring
Copy link
Contributor Author

(I somehow accidentally deleted the member.doc check, just readded it in the Amend)

@stackotter
Copy link
Owner

Whoops, I somehow finished my review but didn't submit it so my comment has been sitting in limbo hahah

@MiaKoring
Copy link
Contributor Author

MiaKoring commented Sep 20, 2025

I’m so sorry. I just didn’t read it correctly… now its correct…. (I hope)

(I added a pre commit hook locally to run generate.sh, format_and_lint.sh and test.sh, so it hopefully won't happen again)

Copy link
Owner

@stackotter stackotter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hahah all good, looks great now

@stackotter stackotter merged commit 6ddacb9 into stackotter:main Sep 21, 2025
11 checks passed
@MiaKoring MiaKoring deleted the feat/hover-modifier branch September 21, 2025 17:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants