1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-03 07:10:04 -04:00

Fix widgets being styled with the wrong state on their first pass

`Ui::widget_style` reads the widget state from the response of the
previous pass. When there is no such response yet it fell back to
`WidgetState::Inactive`, styling the widget wrong for one pass.
Now we request a discard instead, so the widget is painted only once
we know its state.

Also make the default `SeparatorStyle` read `noninteractive.bg_stroke`
directly: a separator is never interactive, so its stroke should not
depend on the widget state. `inactive.bg_stroke` is `Stroke::NONE`,
which made the separator invisible.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Emil Ernerfeldt
2026-08-04 14:30:25 +02:00
parent 1f3e6386b2
commit 7390932ab6
2 changed files with 14 additions and 9 deletions

View File

@@ -143,12 +143,12 @@ impl StyleProvider<LabelStyle> for DefaultStyle {
impl StyleProvider<SeparatorStyle> for DefaultStyle { impl StyleProvider<SeparatorStyle> for DefaultStyle {
fn style(&mut self, modifiers: &StyleArgs<'_>) -> SeparatorStyle { fn style(&mut self, modifiers: &StyleArgs<'_>) -> SeparatorStyle {
let StyleArgs { ctx, .. } = modifiers; let StyleArgs { style, .. } = modifiers;
let ws: BaseStyle = ctx.get_widget_style(modifiers);
SeparatorStyle { SeparatorStyle {
spacing: 6.0, spacing: 6.0,
stroke: ws.frame.stroke, // A separator is never interactive, so its stroke doesn't depend on the widget state:
stroke: style.visuals.widgets.noninteractive.bg_stroke,
} }
} }
} }

View File

@@ -8,7 +8,7 @@ pub use self::{style_provider::StyleProvider, themes::Themes};
use crate::{ use crate::{
Ui, Ui,
widget_style::{Classes, StyleArgs, WidgetStyle}, widget_style::{Classes, StyleArgs, WidgetState, WidgetStyle},
}; };
impl Ui { impl Ui {
@@ -19,11 +19,16 @@ impl Ui {
id: crate::Id, id: crate::Id,
classes: &Classes, classes: &Classes,
) -> S { ) -> S {
// Fetch the current state of the widget // Fetch the state of the widget, as it was in the previous pass
let state = self let state = if let Some(response) = self.read_response(id) {
.read_response(id) response.widget_state()
.map(|r| r.widget_state()) } else {
.unwrap_or_default(); // We don't know the state of the widget yet, so we would style it wrong.
// Discard this pass and style it correctly in the next one.
self.ctx()
.request_discard("Widget style depends on a widget response we don't have yet");
WidgetState::default()
};
self.get_widget_style::<S>(&StyleArgs { self.get_widget_style::<S>(&StyleArgs {
classes, classes,