minor optimizations: fix extra changed event emission

This commit is contained in:
yggverse 2025-10-12 01:27:02 +03:00
parent ffca1d3d60
commit 4998ec62c1
2 changed files with 62 additions and 43 deletions

View file

@ -83,21 +83,35 @@ impl Item {
let page = page.clone(); let page = page.clone();
move |this, _| { move |this, _| {
this.set_enabled(false); this.set_enabled(false);
if let Some(uri) = page.navigation.request.home() { match page.navigation.request.home() {
Some(uri) => {
let request = uri.to_string(); let request = uri.to_string();
page.navigation.request.entry.set_text(&request); // prevent `changed` event extra emission
client.handle(&request, true, false); // but make sure the entry is always up-to-date
if page.navigation.request.entry.text() != request {
page.navigation.request.entry.set_text(&request)
}
client.handle(&request, true, false)
}
None => panic!(), // unexpected
} }
} }
}); });
action.load.connect_activate({ action.load.connect_activate({
let page = page.clone(); let c = client.clone();
let client = client.clone(); let e = page.navigation.request.entry.clone();
move |request, is_snap_history, is_redirect| { move |request, is_snap_history, is_redirect| {
if let Some(request) = request { match request {
page.navigation.request.entry.set_text(&request); Some(request) => {
client.handle(&request, is_snap_history, is_redirect); // prevent `changed` event extra emission
// but make sure the entry is always up-to-date
if e.text() != request {
e.set_text(&request)
}
c.handle(&request, is_snap_history, is_redirect)
}
None => panic!(), // unexpected
} }
} }
}); });
@ -144,11 +158,13 @@ impl Item {
}); });
// Handle immediately on request // Handle immediately on request
if let Some(request) = request { if is_load && let Some(request) = request {
page.navigation.request.entry.set_text(request); // prevent `changed` event extra emission
if is_load { // but make sure the entry is always up-to-date
client.handle(request, true, false) if page.navigation.request.entry.text() != request {
page.navigation.request.entry.set_text(request)
} }
client.handle(request, true, false)
} }
Self { Self {

View file

@ -60,10 +60,10 @@ impl Request {
}; };
let c = gtk::EventControllerKey::builder().build(); let c = gtk::EventControllerKey::builder().build();
c.connect_key_pressed({ c.connect_key_pressed({
let entry = entry.clone(); let e = entry.clone();
let suggestion = suggestion.clone(); let s = suggestion.clone();
move |_, k, _, m| { move |_, k, _, m| {
if suggestion.is_visible() if s.is_visible()
&& !matches!( && !matches!(
m, m,
ModifierType::SHIFT_MASK ModifierType::SHIFT_MASK
@ -72,20 +72,21 @@ impl Request {
) )
{ {
if matches!(k, Key::Up | Key::KP_Up | Key::Page_Up | Key::KP_Page_Up) { if matches!(k, Key::Up | Key::KP_Up | Key::Page_Up | Key::KP_Page_Up) {
if !suggestion.back() { if !s.back() {
entry.error_bell() e.error_bell()
} }
return Propagation::Stop; return Propagation::Stop;
} else if matches!( } else if matches!(
k, k,
Key::Down | Key::KP_Down | Key::Page_Down | Key::KP_Page_Down Key::Down | Key::KP_Down | Key::Page_Down | Key::KP_Page_Down
) { ) {
if !suggestion.next() { if !s.next() {
entry.error_bell() e.error_bell()
} }
return Propagation::Stop; return Propagation::Stop;
} }
} }
s.hide();
Propagation::Proceed Propagation::Proceed
} }
}); });
@ -116,7 +117,15 @@ impl Request {
entry.connect_has_focus_notify({ entry.connect_has_focus_notify({
let i = info.clone(); let i = info.clone();
move |e| update_secondary_icon(e, &i.borrow()) let s = suggestion.clone();
move |this| {
// toggle 'go to' button
update_secondary_icon(this, &i.borrow());
// hide suggestions on focus left this entry
if this.focus_child().is_none_or(|child| !child.has_focus()) {
s.hide()
}
}
}); });
suggestion suggestion
@ -128,20 +137,20 @@ impl Request {
let p = profile.clone(); let p = profile.clone();
let r = proxy_resolver.clone(); let r = proxy_resolver.clone();
let s = suggestion.clone(); let s = suggestion.clone();
move |e| { move |this| {
// Allocate once // Allocate once
let t = e.text(); let t = this.text();
// Update actions // Update actions
a.reload.set_enabled(!t.is_empty()); a.reload.set_enabled(!t.is_empty());
a.home.set_enabled(home(e).is_some()); a.home.set_enabled(home(this).is_some());
// Update icons // Update icons
update_primary_icon(e, &p); update_primary_icon(this, &p);
update_secondary_icon(e, &i.borrow()); update_secondary_icon(this, &i.borrow());
refresh_proxy_resolver(this, &p, &r);
// Show search suggestions // Show search suggestions
if e.focus_child().is_some() { if this.focus_child().is_some() {
s.update(Some(50)); // @TODO optional s.update(Some(50)) // @TODO optional
} }
refresh_proxy_resolver(e, &p, &r)
} }
})); // `suggestion` wants `signal_handler_id` to block this event on autocomplete navigation })); // `suggestion` wants `signal_handler_id` to block this event on autocomplete navigation
@ -154,22 +163,16 @@ impl Request {
} }
}); });
entry.connect_has_focus_notify({
let s = suggestion.clone();
move |_| s.hide()
});
entry.connect_state_flags_changed({
// Define last focus state container
let has_focus = Cell::new(false);
move |this, state| {
// Select entire text on first click (release) // Select entire text on first click (release)
// this behavior implemented in most web-browsers, // this behavior implemented in most web-browsers,
// to simply overwrite current request with new value // to simply overwrite current request with new value
// Note: // Note:
// * Custom GestureClick is not an option here, as GTK Entry has default controller // * Custom GestureClick is not an option here, as GTK Entry has default controller
// * This is experimental feature does not follow native GTK behavior @TODO make optional // * This is experimental feature does not follow native GTK behavior @TODO make optional
if !has_focus.replace(state.contains(StateFlags::FOCUS_WITHIN)) entry.connect_state_flags_changed({
let had_focus = Cell::new(false);
move |this, state| {
if !had_focus.replace(state.contains(StateFlags::FOCUS_WITHIN))
&& state.contains(StateFlags::ACTIVE | StateFlags::FOCUS_WITHIN) && state.contains(StateFlags::ACTIVE | StateFlags::FOCUS_WITHIN)
&& this.selection_bounds().is_none() && this.selection_bounds().is_none()
{ {