[fractal/fractal-next] content: Reuse gio::MenuModel for event context menu



commit dc5a9f0dbf1e2299dc97b125a973a9a744d3e2a6
Author: Julian Sparber <julian sparber net>
Date:   Wed Dec 1 17:59:31 2021 +0100

    content: Reuse gio::MenuModel for event context menu
    
    This creates the gio::MenuModel only once which reduces the time needed
    from over 300us to around 1us.

 src/session/content/room_history/item_row.rs         |  2 +-
 src/session/content/room_history/message_row/text.rs |  3 +--
 src/session/media_viewer.rs                          |  4 ++--
 src/session/room/event_actions.rs                    | 20 ++++++++++++++++----
 4 files changed, 20 insertions(+), 9 deletions(-)
---
diff --git a/src/session/content/room_history/item_row.rs b/src/session/content/room_history/item_row.rs
index 9d12cbde..5f48008f 100644
--- a/src/session/content/room_history/item_row.rs
+++ b/src/session/content/room_history/item_row.rs
@@ -117,7 +117,7 @@ impl ItemRow {
             match item.type_() {
                 ItemType::Event(event) => {
                     if self.context_menu().is_none() {
-                        self.set_context_menu(Some(&Self::event_menu_model()));
+                        self.set_context_menu(Some(Self::event_menu_model()));
                     }
                     self.set_event_actions(Some(event));
 
diff --git a/src/session/content/room_history/message_row/text.rs 
b/src/session/content/room_history/message_row/text.rs
index c28ce502..245913b4 100644
--- a/src/session/content/room_history/message_row/text.rs
+++ b/src/session/content/room_history/message_row/text.rs
@@ -324,8 +324,7 @@ fn set_label_styles(w: &gtk::Label) {
     w.set_valign(gtk::Align::Start);
     w.set_halign(gtk::Align::Fill);
     w.set_selectable(true);
-    let menu_model = ItemRow::event_menu_model();
-    w.set_extra_menu(Some(&menu_model));
+    w.set_extra_menu(Some(ItemRow::event_menu_model()));
 }
 
 fn create_widget_for_html_block(block: &HtmlBlock) -> gtk::Widget {
diff --git a/src/session/media_viewer.rs b/src/session/media_viewer.rs
index b5f8a212..28eda93e 100644
--- a/src/session/media_viewer.rs
+++ b/src/session/media_viewer.rs
@@ -110,8 +110,8 @@ mod imp {
             self.parent_constructed(obj);
 
             let menu_model = Some(Self::Type::event_menu_model());
-            self.menu_full.set_menu_model(menu_model.as_ref());
-            obj.set_context_menu(menu_model.as_ref());
+            self.menu_full.set_menu_model(menu_model);
+            obj.set_context_menu(menu_model);
 
             // Bind `fullscreened` to the window property of the same name.
             obj.connect_notify_local(Some("root"), |obj, _| {
diff --git a/src/session/room/event_actions.rs b/src/session/room/event_actions.rs
index ba93fe0e..de99e4e7 100644
--- a/src/session/room/event_actions.rs
+++ b/src/session/room/event_actions.rs
@@ -2,6 +2,7 @@ use gettextrs::gettext;
 use gtk::{gio, glib, glib::clone, prelude::*};
 use log::error;
 use matrix_sdk::ruma::events::{room::message::MessageType, AnyMessageEventContent};
+use once_cell::sync::Lazy;
 
 use crate::{
     matrix_error::UserFacingError,
@@ -11,6 +12,12 @@ use crate::{
     Error, Window,
 };
 
+// This is only save because the trait `EventActions` can
+// only be implemented on `gtk::Widgets` that run only on the main thread
+struct MenuModelSendSync(gio::MenuModel);
+unsafe impl Send for MenuModelSendSync {}
+unsafe impl Sync for MenuModelSendSync {}
+
 pub trait EventActions
 where
     Self: IsA<gtk::Widget>,
@@ -18,10 +25,15 @@ where
     <Self as glib::clone::Downgrade>::Weak: glib::clone::Upgrade<Strong = Self>,
 {
     /// The `MenuModel` for common event actions.
-    fn event_menu_model() -> gio::MenuModel {
-        gtk::Builder::from_resource("/org/gnome/FractalNext/event-menu.ui")
-            .object("menu_model")
-            .unwrap()
+    fn event_menu_model() -> &'static gio::MenuModel {
+        static MODEL: Lazy<MenuModelSendSync> = Lazy::new(|| {
+            MenuModelSendSync(
+                gtk::Builder::from_resource("/org/gnome/FractalNext/event-menu.ui")
+                    .object::<gio::MenuModel>("menu_model")
+                    .unwrap(),
+            )
+        });
+        &MODEL.0
     }
 
     /// Set the actions available on `self` for `event`.


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]