From dd86a9ebec67bf103e79bdfd1a2377cbe832bc03 Mon Sep 17 00:00:00 2001 From: "Ngo Iok Ui (Wu Yu Wei)" Date: Sun, 16 Oct 2022 16:59:14 +0800 Subject: [PATCH] refactor(linux): reduce channel redirect (#588) * refactor(linux): reduce channel redirect * Add version bump in change file Co-authored-by: Wu Yu Wei --- .changes/tx-reduce.md | 5 ++++ src/platform_impl/linux/event_loop.rs | 38 +++++++++++---------------- src/platform_impl/linux/window.rs | 16 +++++------ 3 files changed, 29 insertions(+), 30 deletions(-) create mode 100644 .changes/tx-reduce.md diff --git a/.changes/tx-reduce.md b/.changes/tx-reduce.md new file mode 100644 index 000000000..62c54c3b9 --- /dev/null +++ b/.changes/tx-reduce.md @@ -0,0 +1,5 @@ +--- +"tao": patch +--- + +On Linux, reduce channel redirect. Now sending user events and redraw request will send to event loops directly. diff --git a/src/platform_impl/linux/event_loop.rs b/src/platform_impl/linux/event_loop.rs index 4fef2ef07..21ada67e9 100644 --- a/src/platform_impl/linux/event_loop.rs +++ b/src/platform_impl/linux/event_loop.rs @@ -8,11 +8,11 @@ use std::{ error::Error, process, rc::Rc, - sync::mpsc::SendError, time::Instant, }; use cairo::{RectangleInt, Region}; +use crossbeam_channel::SendError; use gdk::{Cursor, CursorType, EventKey, EventMask, ScrollDirection, WindowEdge, WindowState}; use gio::{prelude::*, Cancellable}; use glib::{source::Priority, Continue, MainContext}; @@ -50,6 +50,8 @@ pub struct EventLoopWindowTarget { pub(crate) windows: Rc>>, /// Window requests sender pub(crate) window_requests_tx: glib::Sender<(WindowId, WindowRequest)>, + /// Draw event sender + pub(crate) draw_tx: crossbeam_channel::Sender, _marker: std::marker::PhantomData, } @@ -98,7 +100,7 @@ pub struct EventLoop { /// Window target. window_target: RootELW, /// User event sender for EventLoopProxy - user_event_tx: glib::Sender, + user_event_tx: crossbeam_channel::Sender>, /// Event queue of EventLoop events: crossbeam_channel::Receiver>, /// Draw queue of EventLoop @@ -134,6 +136,8 @@ impl EventLoop { log::warn!("Failed to send init event to event channel: {}", e); } }); + let draw_tx_ = draw_tx.clone(); + let user_event_tx = event_tx.clone(); // Create event loop window target. let (window_requests_tx, window_requests_rx) = glib::MainContext::channel(Priority::default()); @@ -145,19 +149,10 @@ impl EventLoop { app, windows: Rc::new(RefCell::new(HashSet::new())), window_requests_tx, + draw_tx: draw_tx_, _marker: std::marker::PhantomData, }; - // Create user event channel - let (user_event_tx, user_event_rx) = glib::MainContext::channel(Priority::default()); - let event_tx_ = event_tx.clone(); - user_event_rx.attach(Some(&context), move |event| { - if let Err(e) = event_tx_.send(Event::UserEvent(event)) { - log::warn!("Failed to send user event to event channel: {}", e); - } - Continue(true) - }); - // Window Request window_requests_rx.attach(Some(&context), move |(id, request)| { if let Some(window) = app_.window_by_id(id.0) { @@ -760,13 +755,6 @@ impl EventLoop { Inhibit(false) }); } - WindowRequest::Redraw => { - if let Err(e) = draw_tx.send(id) { - log::warn!("Failed to send redraw event to event channel: {}", e); - } - - window.queue_draw(); - } WindowRequest::Menu(m) => match m { (None, Some(menu_id)) => { if let Err(e) = event_tx.send(Event::MenuEvent { @@ -1055,7 +1043,7 @@ impl EventLoop { /// Used to send custom events to `EventLoop`. #[derive(Debug)] pub struct EventLoopProxy { - user_event_tx: glib::Sender, + user_event_tx: crossbeam_channel::Sender>, } impl Clone for EventLoopProxy { @@ -1075,8 +1063,14 @@ impl EventLoopProxy { pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed> { self .user_event_tx - .send(event) - .map_err(|SendError(error)| EventLoopClosed(error)) + .send(Event::UserEvent(event)) + .map_err(|SendError(event)| { + if let Event::UserEvent(error) = event { + EventLoopClosed(error) + } else { + unreachable!(); + } + }) } } diff --git a/src/platform_impl/linux/window.rs b/src/platform_impl/linux/window.rs index 94520c512..d3de1ae86 100644 --- a/src/platform_impl/linux/window.rs +++ b/src/platform_impl/linux/window.rs @@ -63,6 +63,8 @@ pub struct Window { maximized: Rc, minimized: Rc, fullscreen: RefCell>, + /// Draw event Sender + draw_tx: crossbeam_channel::Sender, } impl Window { @@ -73,6 +75,7 @@ impl Window { ) -> Result { let app = &event_loop_window_target.app; let window_requests_tx = event_loop_window_target.window_requests_tx.clone(); + let draw_tx = event_loop_window_target.draw_tx.clone(); let window = gtk::ApplicationWindow::builder() .application(app) .accept_focus(attributes.focused) @@ -318,14 +321,15 @@ impl Window { log::warn!("Fail to send wire up events request: {}", e); } - if let Err(e) = window_requests_tx.send((window_id, WindowRequest::Redraw)) { - log::warn!("Fail to send redraw request: {}", e); + if let Err(e) = draw_tx.send(window_id) { + log::warn!("Failed to send redraw event to event channel: {}", e); } let win = Self { window_id, window, window_requests_tx, + draw_tx, accel_group, menu_bar, scale_factor, @@ -350,11 +354,8 @@ impl Window { } pub fn request_redraw(&self) { - if let Err(e) = self - .window_requests_tx - .send((self.window_id, WindowRequest::Redraw)) - { - log::warn!("Fail to send redraw request: {}", e); + if let Err(e) = self.draw_tx.send(self.window_id) { + log::warn!("Failed to send redraw event to event channel: {}", e); } } @@ -820,7 +821,6 @@ pub enum WindowRequest { CursorPosition((i32, i32)), CursorIgnoreEvents(bool), WireUpEvents { transparent: bool }, - Redraw, Menu((Option, Option)), SetMenu((Option, AccelGroup, gtk::MenuBar)), GlobalHotKey(u16),