From 3fda9c851ab3507f0d169a6df2ced3bd314717cc Mon Sep 17 00:00:00 2001 From: yggverse Date: Thu, 26 Dec 2024 20:55:02 +0200 Subject: [PATCH] apply escape action to the current page only --- src/app/browser.rs | 4 +- src/app/browser/action/escape.rs | 60 ++++++++++++++++++++++--- src/app/browser/window.rs | 4 ++ src/app/browser/window/tab.rs | 17 +++++-- src/app/browser/window/tab/item/page.rs | 4 +- 5 files changed, 75 insertions(+), 14 deletions(-) diff --git a/src/app/browser.rs b/src/app/browser.rs index 08d2634e..5e5c4ff1 100644 --- a/src/app/browser.rs +++ b/src/app/browser.rs @@ -70,8 +70,8 @@ impl Browser { action.escape.connect_activate({ let widget = widget.clone(); let window = window.clone(); - move || { - window.tab.escape(None); // current tab + move |tab_item_id| { + window.escape(tab_item_id); widget.application_window.set_focus(gtk::Window::NONE); } }); diff --git a/src/app/browser/action/escape.rs b/src/app/browser/action/escape.rs index 922adb3f..d57c97d5 100644 --- a/src/app/browser/action/escape.rs +++ b/src/app/browser/action/escape.rs @@ -1,4 +1,8 @@ -use gtk::{gio::SimpleAction, glib::uuid_string_random, prelude::ActionExt}; +use gtk::{ + gio::SimpleAction, + glib::{uuid_string_random, GString}, + prelude::{ActionExt, ToVariant}, +}; /// [SimpleAction](https://docs.gtk.org/gio/class.SimpleAction.html) wrapper for `Escape` action of `Browser` group pub struct Escape { @@ -11,23 +15,65 @@ impl Escape { /// Create new `Self` pub fn new() -> Self { Self { - simple_action: SimpleAction::new(&uuid_string_random(), None), + simple_action: SimpleAction::new_stateful( + &uuid_string_random(), + None, + &String::new().to_variant(), + ), } } // Actions /// Emit [activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal - /// with formatted for this action [Variant](https://docs.gtk.org/glib/struct.Variant.html) value - pub fn activate(&self) { - self.simple_action.activate(None); // @TODO custom value + /// * this action reset previous state for action after activation + pub fn activate_stateful_once(&self, tab_item_id: Option) { + // Save current state in memory + let _tab_item_id = state(&self.simple_action); + + // Apply requested state + self.change_state(tab_item_id); + + // Activate action + self.simple_action.activate(None); + + // Return previous state + self.change_state(_tab_item_id); + } + + /// Change action [state](https://docs.gtk.org/gio/method.SimpleAction.set_state.html) + /// * set default state on `None` + pub fn change_state(&self, state: Option) { + self.simple_action.change_state( + &match state { + Some(value) => value.to_string(), + None => String::new(), + } + .to_variant(), + ) } // Events /// Define callback function for /// [SimpleAction::activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal - pub fn connect_activate(&self, callback: impl Fn() + 'static) { - self.simple_action.connect_activate(move |_, _| callback()); + pub fn connect_activate(&self, callback: impl Fn(Option) + 'static) { + self.simple_action + .connect_activate(move |this, _| callback(state(this))); + } +} + +/// Shared helper to get C-based action state in Optional format +fn state(this: &SimpleAction) -> Option { + let state = this + .state() + .expect("State value required") + .get::() + .expect("Parameter type does not match `String`"); + + if state.is_empty() { + None + } else { + Some(state.into()) } } diff --git a/src/app/browser/window.rs b/src/app/browser/window.rs index 32ac47ef..33fb8fd0 100644 --- a/src/app/browser/window.rs +++ b/src/app/browser/window.rs @@ -119,6 +119,10 @@ impl Window { } // Actions + pub fn escape(&self, tab_item_id: Option) { + self.tab.escape(tab_item_id); + } + pub fn update(&self, tab_item_id: Option) { self.tab.update(tab_item_id); } diff --git a/src/app/browser/window/tab.rs b/src/app/browser/window/tab.rs index 4ffcf480..204ed971 100644 --- a/src/app/browser/window/tab.rs +++ b/src/app/browser/window/tab.rs @@ -176,10 +176,19 @@ impl Tab { self.widget.close_all(); } - // Toggle search widget - pub fn escape(&self, page_position: Option) { - if let Some(item) = self.item(page_position) { - item.page.escape(); + // Toggle escape action for specified or current item + pub fn escape(&self, item_id: Option) { + match item_id { + Some(id) => { + if let Some(item) = self.index.borrow().get(&id) { + item.page.escape() + } + } + None => { + if let Some(item) = self.item(None) { + item.page.escape(); + } + } } } diff --git a/src/app/browser/window/tab/item/page.rs b/src/app/browser/window/tab/item/page.rs index b217bd9d..d92fad13 100644 --- a/src/app/browser/window/tab/item/page.rs +++ b/src/app/browser/window/tab/item/page.rs @@ -176,7 +176,9 @@ impl Page { const DEFAULT_MAX_REDIRECT_COUNT: usize = 10; // Move focus out from navigation entry - self.browser_action.escape.activate(); + self.browser_action + .escape + .activate_stateful_once(Some(self.id.as_str().into())); // Initially disable find action self.window_action.find.simple_action.set_enabled(false);