Removing widgets would affect the visual order, and sometimes nodes just
aren't available anymore. It might be that this should be cleaned up
more aggressively during widget removal, but by ignoring the removed
nodes, the code just becomes more resilliant to similar edge cases in
the future.
During the change callback process, unlocked is called to allow the
change callbacks to run while the dynamic is unlocked. The error with
the previous version of this code is that the during_callback_state was
always overwritten when being returned. The problem is that another
thread could currently have the mutex locked and could have stored its
own state -- which can happen if two threads are both trying to invoke
change callbacks at the same time.
By moving the state saving and reloading to only happen when the mutex
guard is acquired, we can ensure that interleaving threads will work
correctly.
Refs #153
This turned out to be "needed" by the debug window due to how dynamic
locking was nested when a for_each call was being invoked. To keep the
code simple, for_each_subsequent was added.
I'm not sure exactly what caused this that other simpler cases were not,
but essentially nodes were already removed once by the time this loop is
evaluated, so we can skip adding them back to the list again.
I had previously had similar logic in here, but I realized I couldn't
reliably detect if cosmic_text had done any wrapping or not. After a
discussion prompted me to see if recaching was happening while
scrolling, I realized I could at least allow the width to be >= the
measured text size and <= the requested layout width.
This prevents recaching while scrolling.
map_each previously was written such that if a chain of mappings fed
each other, a deadlock could occur because while the first one was
mapped, the second callback gets invoked and tries to update the first
value while it's still being held.
This refactor switches from std Mutex to parking_lot, allowing me to
remove a workaround for needing to run drop callbacks in a separate
thread during the drop of a DynamicGuard.
In addition to that change, the lower level `map_generational` calls now
take a DynamicGuard as their parameter. This allows these functions to
drop ownership of the referenced data during the callback.
The map_each implementation takes advantage of this by ensuring that the
guard is dropped before set is invoked, minimizing potential lock overlaps.
With this refactor, some old code of mine with complex validations now works
again.
I originally removed this API to ensure no Cushy widgets were using
winit directly, but I've reintroduced it so that third party widgets can
still interact with winit if needed.
When an overlay handle dropped directly after pushing a new overlay, it
was possible for new overlays to be popped off improperly, causing a
subtraction overflow panic later.
Closes#138
This implementation works around most of the locking issues that arose
the first few times I tried fixing this. Unfortunately it's been just
long enough for me to forget how I triggered some catastrophic issues in
the past, but all of the current examples that would invoke this
behavior continue to work, and some of the side projects that have some
weird usages also still work.
This may seem like a lot of options, but here's the reasoning:
- The CSS spec offers four variations: Simplified/Traditional and
Formal/Informal. This spec defines a character set for all for
variations, and it also associates rules for omitting digits in the
informal variants.
- The chinese_number crate does not implement a variant that includes
the tens digit, as required by the cSS spec for the formal variants.
To be able to provide the enumerations that the CSS spec offers *and* to
provide the variations that the chinese_number crate supports, I've aded
8 total list styles for selecting a specific Chinese variation.
Technically nominals supports even more options, but the myriad counting
scale coveres u128::MAX and seems to be the most common counting style.