From 2c344c9dc33101ce6923d2b27522e20c8ee37f13 Mon Sep 17 00:00:00 2001 From: Chooooooo Date: Sat, 21 Sep 2024 22:34:32 +0900 Subject: [PATCH 01/18] feat(wayland): Add custom header bar with window controls The changes add a custom header bar with window control buttons (close, maximize/restore, minimize) to the Linux Wayland platform implementation. This provides a consistent user experience for window management across platforms. The header bar is implemented using GTK widgets and is added to the top of the application window. The drag area of the header bar is also used to enable window moving and resizing functionality. --- src/platform_impl/linux/mod.rs | 1 + src/platform_impl/linux/wayland/display.rs | 140 +++++++++++++++++++++ src/platform_impl/linux/wayland/mod.rs | 5 + src/platform_impl/linux/window.rs | 9 ++ 4 files changed, 155 insertions(+) create mode 100644 src/platform_impl/linux/wayland/display.rs create mode 100644 src/platform_impl/linux/wayland/mod.rs diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index a0b8c5d30..d56f76413 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -21,6 +21,7 @@ mod window; pub mod taskbar; pub mod x11; +pub mod wayland; pub use self::keycode::{keycode_from_scancode, keycode_to_scancode}; pub(crate) use event_loop::PlatformSpecificEventLoopAttributes; diff --git a/src/platform_impl/linux/wayland/display.rs b/src/platform_impl/linux/wayland/display.rs new file mode 100644 index 000000000..e33c34b6a --- /dev/null +++ b/src/platform_impl/linux/wayland/display.rs @@ -0,0 +1,140 @@ +use gtk::{ + prelude::*, + HeaderBar, + Button, + Image, + ApplicationWindow, + EventBox, + Orientation, + gdk::EventMask, + glib::{self}, +}; +use std::cell::RefCell; +use std::rc::Rc; + +pub struct WlHeader; + +impl WlHeader { + pub fn setup(window: &ApplicationWindow) { + let header = HeaderBar::new(); + header.set_show_close_button(false); + + let close_button = Self::create_header_button("window-close-symbolic"); + let maximize_button = Self::create_header_button("window-maximize-symbolic"); + let minimize_button = Self::create_header_button("window-minimize-symbolic"); + + Self::connect_close_button(close_button.clone(), window); + Self::connect_maximize_button(maximize_button.clone(), window); + Self::connect_minimize_button(minimize_button.clone(), window); + + header.pack_end(&close_button); + header.pack_end(&maximize_button); + header.pack_end(&minimize_button); + + let drag_area = EventBox::new(); + drag_area.add(&header); + drag_area.add_events(EventMask::BUTTON_PRESS_MASK | EventMask::BUTTON_RELEASE_MASK | EventMask::POINTER_MOTION_MASK); + + Self::connect_drag_area(&drag_area, window); + + let vbox = gtk::Box::new(Orientation::Vertical, 0); + vbox.pack_start(&drag_area, false, false, 0); + + window.add(&vbox); + window.set_titlebar(Some(&vbox)); + } + + fn create_header_button(icon_name: &str) -> Button { + let button = Button::new(); + let icon = Image::from_icon_name(Some(icon_name), gtk::IconSize::Button); + button.set_image(Some(&icon)); + button + } + + fn connect_close_button(button: Button, window: &ApplicationWindow) { + let window_weak = window.downgrade(); + button.connect_clicked(move |_| { + if let Some(window) = window_weak.upgrade() { + window.close(); + } + }); + } + + fn connect_maximize_button(button: Button, window: &ApplicationWindow) { + let window_weak = window.downgrade(); + button.connect_clicked(move |_| { + if let Some(window) = window_weak.upgrade() { + if window.is_maximized() { + window.unmaximize(); + } else { + window.set_resizable(true); + window.maximize(); + } + } + }); + } + + fn connect_minimize_button(button: Button, window: &ApplicationWindow) { + let window_weak = window.downgrade(); + button.connect_clicked(move |_| { + if let Some(window) = window_weak.upgrade() { + window.iconify(); + } + }); + } + + fn connect_drag_area(drag_area: &EventBox, window: &ApplicationWindow) { + let window_weak = Rc::new(window.downgrade()); + let press_pos = Rc::new(RefCell::new((0, 0))); + let state = Rc::new(RefCell::new((false, false))); // (moving, resizing) + + let press_pos_clone = press_pos.clone(); + let state_clone = state.clone(); + let window_weak_clone = window_weak.clone(); + drag_area.connect_button_press_event(move |_, event| { + if let Some(_window) = window_weak_clone.upgrade() { + let mut state = state_clone.borrow_mut(); + if event.button() == 1 { // 좌클릭 + *press_pos_clone.borrow_mut() = (event.position().0 as i32, event.position().1 as i32); + state.0 = true; // moving = true + } else if event.button() == 3 { // 우클릭 + state.1 = true; // resizing = true + } + } + glib::Propagation::Proceed + }); + + let state_clone = state.clone(); + drag_area.connect_button_release_event(move |_, _| { + let mut state = state_clone.borrow_mut(); + state.0 = false; // moving = false + state.1 = false; // resizing = false + glib::Propagation::Proceed + }); + + let press_pos_clone = press_pos.clone(); + let state_clone = state.clone(); + let window_weak_clone = window_weak.clone(); + drag_area.connect_motion_notify_event(move |_, event| { + if let Some(window) = window_weak_clone.upgrade() { + let state = state_clone.borrow(); + let press_pos = press_pos_clone.borrow(); + if state.0 { // if moving + let (win_x, win_y) = window.position(); + window.move_( + win_x + (event.position().0 as i32 - press_pos.0), + win_y + (event.position().1 as i32 - press_pos.1) + ); + } else if state.1 { // if resizing + let (width, height) = window.size(); + window.resize( + width + (event.position().0 as i32 - press_pos.0), + height + (event.position().1 as i32 - press_pos.1) + ); + } + } + glib::Propagation::Proceed + }); + } + +} \ No newline at end of file diff --git a/src/platform_impl/linux/wayland/mod.rs b/src/platform_impl/linux/wayland/mod.rs new file mode 100644 index 000000000..4c173750f --- /dev/null +++ b/src/platform_impl/linux/wayland/mod.rs @@ -0,0 +1,5 @@ +// Copyright 2014-2021 The winit contributors +// Copyright 2021-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 + +pub mod display; \ No newline at end of file diff --git a/src/platform_impl/linux/window.rs b/src/platform_impl/linux/window.rs index 07a1ca9bc..7f6eb70c3 100644 --- a/src/platform_impl/linux/window.rs +++ b/src/platform_impl/linux/window.rs @@ -27,6 +27,7 @@ use crate::{ CursorIcon, Fullscreen, ProgressBarState, ResizeDirection, Theme, UserAttentionType, WindowAttributes, WindowSizeConstraints, }, + platform_impl::wayland::display::WlHeader, }; use super::{ @@ -77,6 +78,7 @@ impl Window { 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 is_wayland = event_loop_window_target.is_wayland(); let mut window_builder = gtk::ApplicationWindow::builder() .application(app) @@ -87,6 +89,10 @@ impl Window { let window = window_builder.build(); + if is_wayland { + WlHeader::setup(&window); + } + let window_id = WindowId(window.id()); event_loop_window_target .windows @@ -103,6 +109,9 @@ impl Window { window.resize(width, height); if attributes.maximized { + if is_wayland { + window.set_resizable(true); + } window.maximize(); } From 853f5ee478c5d08b8ac3937170ffb4fe9ce2523f Mon Sep 17 00:00:00 2001 From: Chooooooo Date: Sun, 22 Sep 2024 23:30:02 +0900 Subject: [PATCH 02/18] feat(window): Add maximized state check when setting window maximized ## Explanation The changes made in this commit ensure that the window is only maximized if it is also resizable. This is to prevent issues where a non-resizable window is maximized, which could lead to unexpected behavior. The main changes are: 1. In the `set_maximized` function, the code checks if the window is resizable before maximizing it. If it's not resizable, the window is not maximized. 2. In the `is_maximizable` function, the code checks if the window is resizable and if the maximized state is true before returning `true`. These changes improve the overall behavior and consistency of the window maximization functionality. --- src/platform_impl/linux/event_loop.rs | 42 +++- src/platform_impl/linux/wayland/display.rs | 219 +++++++++------------ src/platform_impl/linux/window.rs | 9 +- 3 files changed, 131 insertions(+), 139 deletions(-) diff --git a/src/platform_impl/linux/event_loop.rs b/src/platform_impl/linux/event_loop.rs index 6d84587b5..209732598 100644 --- a/src/platform_impl/linux/event_loop.rs +++ b/src/platform_impl/linux/event_loop.rs @@ -262,6 +262,7 @@ impl EventLoop { }; let mut taskbar = TaskbarIndicator::new(); + let is_wayland = window_target.is_wayland(); // Window Request window_requests_rx.attach(Some(&context), move |(id, request)| { @@ -293,7 +294,7 @@ impl EventLoop { } } WindowRequest::Maximized(maximized) => { - if maximized { + if maximized && window.is_resizable() { window.maximize(); } else { window.unmaximize(); @@ -421,6 +422,33 @@ impl EventLoop { | EventMask::SCROLL_MASK, ); + const TITLEBAR_HEIGHT: f64 = 30.0; + const LMB: u32 = 1; + // Wayland add Events + if is_wayland { + window.connect_button_press_event(move |window, event| { + if event.button() == LMB { + let (x, y) = event.root(); + let (window_x, window_y) = window.position(); + let (window_x, window_y) = (window_x as f64, window_y as f64); + + let border_width = window.border_width() as f64; + let (window_width, _) = window.size(); + let window_width = window_width as f64; + + if x > window_x + border_width && + x < window_x + window_width - border_width && + y > window_y + border_width && + y < window_y + border_width + TITLEBAR_HEIGHT + { + window.begin_move_drag(LMB as i32, x as i32, y as i32, event.time()); + return glib::Propagation::Stop; + } + } + glib::Propagation::Proceed + }); + } + let fullscreen = Rc::new(AtomicBool::new(fullscreen)); let fullscreen_ = fullscreen.clone(); window.connect_window_state_event(move |_window, event| { @@ -462,15 +490,10 @@ impl EventLoop { glib::Propagation::Proceed }); window.connect_button_press_event(move |window, event| { - if !window.is_decorated() - && window.is_resizable() - && !window.is_maximized() - && event.button() == 1 - { - if let Some(window) = window.window() { + if event.button() == LMB { let (cx, cy) = event.root(); let (left, top) = window.position(); - let (w, h) = (window.width(), window.height()); + let (w, h) = window.size(); let (right, bottom) = (left + w, top + h); let border = window.scale_factor() * 5; let edge = crate::window::hit_test( @@ -489,11 +512,10 @@ impl EventLoop { WindowEdge::__Unknown(_) => (), _ => { // FIXME: calling `window.begin_resize_drag` uses the default cursor, it should show a resizing cursor instead - window.begin_resize_drag(edge, 1, cx as i32, cy as i32, event.time()) + window.begin_resize_drag(edge, LMB as i32, cx as i32, cy as i32, event.time()) } } } - } glib::Propagation::Proceed }); diff --git a/src/platform_impl/linux/wayland/display.rs b/src/platform_impl/linux/wayland/display.rs index e33c34b6a..88565cd1e 100644 --- a/src/platform_impl/linux/wayland/display.rs +++ b/src/platform_impl/linux/wayland/display.rs @@ -1,140 +1,107 @@ use gtk::{ - prelude::*, - HeaderBar, - Button, - Image, - ApplicationWindow, - EventBox, - Orientation, - gdk::EventMask, - glib::{self}, + prelude::*, + HeaderBar, + Button, + ToggleButton, + Image, + ApplicationWindow, + glib::{self}, + gdk::{self}, }; -use std::cell::RefCell; -use std::rc::Rc; - pub struct WlHeader; impl WlHeader { - pub fn setup(window: &ApplicationWindow) { - let header = HeaderBar::new(); - header.set_show_close_button(false); - - let close_button = Self::create_header_button("window-close-symbolic"); - let maximize_button = Self::create_header_button("window-maximize-symbolic"); - let minimize_button = Self::create_header_button("window-minimize-symbolic"); - - Self::connect_close_button(close_button.clone(), window); - Self::connect_maximize_button(maximize_button.clone(), window); - Self::connect_minimize_button(minimize_button.clone(), window); - - header.pack_end(&close_button); - header.pack_end(&maximize_button); - header.pack_end(&minimize_button); - - let drag_area = EventBox::new(); - drag_area.add(&header); - drag_area.add_events(EventMask::BUTTON_PRESS_MASK | EventMask::BUTTON_RELEASE_MASK | EventMask::POINTER_MOTION_MASK); + pub fn setup(window: &ApplicationWindow) { + let header = HeaderBar::new(); + header.set_show_close_button(false); - Self::connect_drag_area(&drag_area, window); + let close_button = Self::create_header_button("window-close-symbolic"); + let maximize_button = Self::create_header_toggle_button("window-maximize-symbolic"); + let minimize_button = Self::create_header_button("window-minimize-symbolic"); - let vbox = gtk::Box::new(Orientation::Vertical, 0); - vbox.pack_start(&drag_area, false, false, 0); + Self::connect_close_button(close_button.clone(), window); + Self::connect_maximize_button(maximize_button.clone(), window); + Self::connect_minimize_button(minimize_button.clone(), window); - window.add(&vbox); - window.set_titlebar(Some(&vbox)); - } - - fn create_header_button(icon_name: &str) -> Button { - let button = Button::new(); + header.pack_end(&close_button); + header.pack_end(&maximize_button); + header.pack_end(&minimize_button); + + window.set_titlebar(Some(&header)); + } + + fn create_header_button(icon_name: &str) -> Button { + let button = Button::new(); + let icon = Image::from_icon_name(Some(icon_name), gtk::IconSize::Button); + button.set_image(Some(&icon)); + button + } + + fn create_header_toggle_button(icon_name: &str) -> ToggleButton { + let button = ToggleButton::new(); let icon = Image::from_icon_name(Some(icon_name), gtk::IconSize::Button); button.set_image(Some(&icon)); button - } - - fn connect_close_button(button: Button, window: &ApplicationWindow) { - let window_weak = window.downgrade(); - button.connect_clicked(move |_| { - if let Some(window) = window_weak.upgrade() { - window.close(); - } - }); - } - - fn connect_maximize_button(button: Button, window: &ApplicationWindow) { - let window_weak = window.downgrade(); - button.connect_clicked(move |_| { - if let Some(window) = window_weak.upgrade() { - if window.is_maximized() { - window.unmaximize(); - } else { - window.set_resizable(true); - window.maximize(); - } - } - }); - } - - fn connect_minimize_button(button: Button, window: &ApplicationWindow) { - let window_weak = window.downgrade(); - button.connect_clicked(move |_| { - if let Some(window) = window_weak.upgrade() { - window.iconify(); - } - }); - } - - fn connect_drag_area(drag_area: &EventBox, window: &ApplicationWindow) { - let window_weak = Rc::new(window.downgrade()); - let press_pos = Rc::new(RefCell::new((0, 0))); - let state = Rc::new(RefCell::new((false, false))); // (moving, resizing) + } - let press_pos_clone = press_pos.clone(); - let state_clone = state.clone(); - let window_weak_clone = window_weak.clone(); - drag_area.connect_button_press_event(move |_, event| { - if let Some(_window) = window_weak_clone.upgrade() { - let mut state = state_clone.borrow_mut(); - if event.button() == 1 { // 좌클릭 - *press_pos_clone.borrow_mut() = (event.position().0 as i32, event.position().1 as i32); - state.0 = true; // moving = true - } else if event.button() == 3 { // 우클릭 - state.1 = true; // resizing = true - } - } - glib::Propagation::Proceed - }); + fn connect_close_button(button: Button, window: &ApplicationWindow) { + let window_weak = window.downgrade(); + button.connect_clicked(move |_| { + if let Some(window) = window_weak.upgrade() { + window.close(); + } + }); + } - let state_clone = state.clone(); - drag_area.connect_button_release_event(move |_, _| { - let mut state = state_clone.borrow_mut(); - state.0 = false; // moving = false - state.1 = false; // resizing = false - glib::Propagation::Proceed - }); + fn connect_maximize_button(button: ToggleButton, window: &ApplicationWindow) { + let window_weak = window.downgrade(); + // initial state + if let Some(window) = window_weak.upgrade() { + button.set_active(window.is_maximized()); + button.set_sensitive(window.is_resizable()); + } - let press_pos_clone = press_pos.clone(); - let state_clone = state.clone(); - let window_weak_clone = window_weak.clone(); - drag_area.connect_motion_notify_event(move |_, event| { - if let Some(window) = window_weak_clone.upgrade() { - let state = state_clone.borrow(); - let press_pos = press_pos_clone.borrow(); - if state.0 { // if moving - let (win_x, win_y) = window.position(); - window.move_( - win_x + (event.position().0 as i32 - press_pos.0), - win_y + (event.position().1 as i32 - press_pos.1) - ); - } else if state.1 { // if resizing - let (width, height) = window.size(); - window.resize( - width + (event.position().0 as i32 - press_pos.0), - height + (event.position().1 as i32 - press_pos.1) - ); - } - } - glib::Propagation::Proceed - }); - } - -} \ No newline at end of file + let button_weak = button.downgrade(); + window.connect_is_maximized_notify(move |window| { + if let Some(button) = button_weak.upgrade() { + button.set_active(window.is_maximized()); + } + }); + + let button_weak = button.downgrade(); + window.connect_resizable_notify(move |window| { + if let Some(button) = button_weak.upgrade() { + button.set_sensitive(window.is_resizable()); + } + }); + + //click event + button.connect_toggled(move |button| { + if let Some(window) = window_weak.upgrade() { + if button.is_active() && window.is_resizable() { + window.maximize(); + } else { + window.unmaximize(); + } + } + }); + + // Prevent space key activation in header + button.connect_key_press_event(move |_, event_key| { + if event_key.keyval() == gdk::keys::constants::space { + glib::Propagation::Stop + } else { + glib::Propagation::Proceed + } + }); + } + + fn connect_minimize_button(button: Button, window: &ApplicationWindow) { + let window_weak = window.downgrade(); + button.connect_clicked(move |_| { + if let Some(window) = window_weak.upgrade() { + window.iconify(); + } + }); + } +} diff --git a/src/platform_impl/linux/window.rs b/src/platform_impl/linux/window.rs index 7f6eb70c3..a1df150a7 100644 --- a/src/platform_impl/linux/window.rs +++ b/src/platform_impl/linux/window.rs @@ -108,7 +108,7 @@ impl Window { window.set_default_size(1, 1); window.resize(width, height); - if attributes.maximized { + if attributes.maximized && attributes.resizable { if is_wayland { window.set_resizable(true); } @@ -578,9 +578,12 @@ impl Window { } pub fn set_maximized(&self, maximized: bool) { + let resizable = self.is_resizable(); + let should_maximize = maximized && resizable; + if let Err(e) = self .window_requests_tx - .send((self.window_id, WindowRequest::Maximized(maximized))) + .send((self.window_id, WindowRequest::Maximized(should_maximize))) { log::warn!("Fail to send maximized request: {}", e); } @@ -603,7 +606,7 @@ impl Window { } pub fn is_maximizable(&self) -> bool { - true + self.window.is_resizable() && self.maximized.load(Ordering::Acquire) } pub fn is_closable(&self) -> bool { From 217f9577912ce5685908873b0d404ae1e8a97032 Mon Sep 17 00:00:00 2001 From: Chooooooo Date: Sun, 22 Sep 2024 23:35:33 +0900 Subject: [PATCH 03/18] style(window): code format linting --- src/platform_impl/linux/event_loop.rs | 74 ++++---- src/platform_impl/linux/mod.rs | 2 +- src/platform_impl/linux/wayland/display.rs | 188 ++++++++++----------- src/platform_impl/linux/wayland/mod.rs | 2 +- src/platform_impl/linux/window.rs | 2 +- 5 files changed, 132 insertions(+), 136 deletions(-) diff --git a/src/platform_impl/linux/event_loop.rs b/src/platform_impl/linux/event_loop.rs index 209732598..ce69fb614 100644 --- a/src/platform_impl/linux/event_loop.rs +++ b/src/platform_impl/linux/event_loop.rs @@ -428,21 +428,21 @@ impl EventLoop { if is_wayland { window.connect_button_press_event(move |window, event| { if event.button() == LMB { - let (x, y) = event.root(); - let (window_x, window_y) = window.position(); - let (window_x, window_y) = (window_x as f64, window_y as f64); - - let border_width = window.border_width() as f64; - let (window_width, _) = window.size(); - let window_width = window_width as f64; - - if x > window_x + border_width && - x < window_x + window_width - border_width && - y > window_y + border_width && - y < window_y + border_width + TITLEBAR_HEIGHT + let (x, y) = event.root(); + let (window_x, window_y) = window.position(); + let (window_x, window_y) = (window_x as f64, window_y as f64); + + let border_width = window.border_width() as f64; + let (window_width, _) = window.size(); + let window_width = window_width as f64; + + if x > window_x + border_width + && x < window_x + window_width - border_width + && y > window_y + border_width + && y < window_y + border_width + TITLEBAR_HEIGHT { - window.begin_move_drag(LMB as i32, x as i32, y as i32, event.time()); - return glib::Propagation::Stop; + window.begin_move_drag(LMB as i32, x as i32, y as i32, event.time()); + return glib::Propagation::Stop; } } glib::Propagation::Proceed @@ -491,31 +491,31 @@ impl EventLoop { }); window.connect_button_press_event(move |window, event| { if event.button() == LMB { - let (cx, cy) = event.root(); - let (left, top) = window.position(); - let (w, h) = window.size(); - let (right, bottom) = (left + w, top + h); - let border = window.scale_factor() * 5; - let edge = crate::window::hit_test( - (left, top, right, bottom), - cx as _, - cy as _, - border, - border, - ) - .map(|d| d.to_gtk_edge()) - // we return `WindowEdge::__Unknown` to be ignored later. - // we must return 8 or bigger, otherwise it will be the same as one of the other 7 variants of `WindowEdge` enum. - .unwrap_or(WindowEdge::__Unknown(8)); - // Ignore the `__Unknown` variant so the window receives the click correctly if it is not on the edges. - match edge { - WindowEdge::__Unknown(_) => (), - _ => { - // FIXME: calling `window.begin_resize_drag` uses the default cursor, it should show a resizing cursor instead - window.begin_resize_drag(edge, LMB as i32, cx as i32, cy as i32, event.time()) - } + let (cx, cy) = event.root(); + let (left, top) = window.position(); + let (w, h) = window.size(); + let (right, bottom) = (left + w, top + h); + let border = window.scale_factor() * 5; + let edge = crate::window::hit_test( + (left, top, right, bottom), + cx as _, + cy as _, + border, + border, + ) + .map(|d| d.to_gtk_edge()) + // we return `WindowEdge::__Unknown` to be ignored later. + // we must return 8 or bigger, otherwise it will be the same as one of the other 7 variants of `WindowEdge` enum. + .unwrap_or(WindowEdge::__Unknown(8)); + // Ignore the `__Unknown` variant so the window receives the click correctly if it is not on the edges. + match edge { + WindowEdge::__Unknown(_) => (), + _ => { + // FIXME: calling `window.begin_resize_drag` uses the default cursor, it should show a resizing cursor instead + window.begin_resize_drag(edge, LMB as i32, cx as i32, cy as i32, event.time()) } } + } glib::Propagation::Proceed }); diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index d56f76413..e641a79d1 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -20,8 +20,8 @@ mod util; mod window; pub mod taskbar; -pub mod x11; pub mod wayland; +pub mod x11; pub use self::keycode::{keycode_from_scancode, keycode_to_scancode}; pub(crate) use event_loop::PlatformSpecificEventLoopAttributes; diff --git a/src/platform_impl/linux/wayland/display.rs b/src/platform_impl/linux/wayland/display.rs index 88565cd1e..f35ef0063 100644 --- a/src/platform_impl/linux/wayland/display.rs +++ b/src/platform_impl/linux/wayland/display.rs @@ -1,107 +1,103 @@ use gtk::{ - prelude::*, - HeaderBar, - Button, - ToggleButton, - Image, - ApplicationWindow, - glib::{self}, - gdk::{self}, + gdk::{self}, + glib::{self}, + prelude::*, + ApplicationWindow, Button, HeaderBar, Image, ToggleButton, }; pub struct WlHeader; impl WlHeader { - pub fn setup(window: &ApplicationWindow) { - let header = HeaderBar::new(); - header.set_show_close_button(false); + pub fn setup(window: &ApplicationWindow) { + let header = HeaderBar::new(); + header.set_show_close_button(false); - let close_button = Self::create_header_button("window-close-symbolic"); - let maximize_button = Self::create_header_toggle_button("window-maximize-symbolic"); - let minimize_button = Self::create_header_button("window-minimize-symbolic"); + let close_button = Self::create_header_button("window-close-symbolic"); + let maximize_button = Self::create_header_toggle_button("window-maximize-symbolic"); + let minimize_button = Self::create_header_button("window-minimize-symbolic"); - Self::connect_close_button(close_button.clone(), window); - Self::connect_maximize_button(maximize_button.clone(), window); - Self::connect_minimize_button(minimize_button.clone(), window); + Self::connect_close_button(close_button.clone(), window); + Self::connect_maximize_button(maximize_button.clone(), window); + Self::connect_minimize_button(minimize_button.clone(), window); - header.pack_end(&close_button); - header.pack_end(&maximize_button); - header.pack_end(&minimize_button); - - window.set_titlebar(Some(&header)); - } - - fn create_header_button(icon_name: &str) -> Button { - let button = Button::new(); - let icon = Image::from_icon_name(Some(icon_name), gtk::IconSize::Button); - button.set_image(Some(&icon)); - button - } - - fn create_header_toggle_button(icon_name: &str) -> ToggleButton { - let button = ToggleButton::new(); - let icon = Image::from_icon_name(Some(icon_name), gtk::IconSize::Button); - button.set_image(Some(&icon)); - button - } - - fn connect_close_button(button: Button, window: &ApplicationWindow) { - let window_weak = window.downgrade(); - button.connect_clicked(move |_| { - if let Some(window) = window_weak.upgrade() { - window.close(); - } - }); + header.pack_end(&close_button); + header.pack_end(&maximize_button); + header.pack_end(&minimize_button); + + window.set_titlebar(Some(&header)); + } + + fn create_header_button(icon_name: &str) -> Button { + let button = Button::new(); + let icon = Image::from_icon_name(Some(icon_name), gtk::IconSize::Button); + button.set_image(Some(&icon)); + button + } + + fn create_header_toggle_button(icon_name: &str) -> ToggleButton { + let button = ToggleButton::new(); + let icon = Image::from_icon_name(Some(icon_name), gtk::IconSize::Button); + button.set_image(Some(&icon)); + button + } + + fn connect_close_button(button: Button, window: &ApplicationWindow) { + let window_weak = window.downgrade(); + button.connect_clicked(move |_| { + if let Some(window) = window_weak.upgrade() { + window.close(); + } + }); + } + + fn connect_maximize_button(button: ToggleButton, window: &ApplicationWindow) { + let window_weak = window.downgrade(); + // initial state + if let Some(window) = window_weak.upgrade() { + button.set_active(window.is_maximized()); + button.set_sensitive(window.is_resizable()); } - - fn connect_maximize_button(button: ToggleButton, window: &ApplicationWindow) { - let window_weak = window.downgrade(); - // initial state - if let Some(window) = window_weak.upgrade() { - button.set_active(window.is_maximized()); - button.set_sensitive(window.is_resizable()); + + let button_weak = button.downgrade(); + window.connect_is_maximized_notify(move |window| { + if let Some(button) = button_weak.upgrade() { + button.set_active(window.is_maximized()); + } + }); + + let button_weak = button.downgrade(); + window.connect_resizable_notify(move |window| { + if let Some(button) = button_weak.upgrade() { + button.set_sensitive(window.is_resizable()); + } + }); + + //click event + button.connect_toggled(move |button| { + if let Some(window) = window_weak.upgrade() { + if button.is_active() && window.is_resizable() { + window.maximize(); + } else { + window.unmaximize(); } - - let button_weak = button.downgrade(); - window.connect_is_maximized_notify(move |window| { - if let Some(button) = button_weak.upgrade() { - button.set_active(window.is_maximized()); - } - }); - - let button_weak = button.downgrade(); - window.connect_resizable_notify(move |window| { - if let Some(button) = button_weak.upgrade() { - button.set_sensitive(window.is_resizable()); - } - }); - - //click event - button.connect_toggled(move |button| { - if let Some(window) = window_weak.upgrade() { - if button.is_active() && window.is_resizable() { - window.maximize(); - } else { - window.unmaximize(); - } - } - }); - - // Prevent space key activation in header - button.connect_key_press_event(move |_, event_key| { - if event_key.keyval() == gdk::keys::constants::space { - glib::Propagation::Stop - } else { - glib::Propagation::Proceed - } - }); - } - - fn connect_minimize_button(button: Button, window: &ApplicationWindow) { - let window_weak = window.downgrade(); - button.connect_clicked(move |_| { - if let Some(window) = window_weak.upgrade() { - window.iconify(); - } - }); - } + } + }); + + // Prevent space key activation in header + button.connect_key_press_event(move |_, event_key| { + if event_key.keyval() == gdk::keys::constants::space { + glib::Propagation::Stop + } else { + glib::Propagation::Proceed + } + }); + } + + fn connect_minimize_button(button: Button, window: &ApplicationWindow) { + let window_weak = window.downgrade(); + button.connect_clicked(move |_| { + if let Some(window) = window_weak.upgrade() { + window.iconify(); + } + }); + } } diff --git a/src/platform_impl/linux/wayland/mod.rs b/src/platform_impl/linux/wayland/mod.rs index 4c173750f..d80d8181a 100644 --- a/src/platform_impl/linux/wayland/mod.rs +++ b/src/platform_impl/linux/wayland/mod.rs @@ -2,4 +2,4 @@ // Copyright 2021-2023 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 -pub mod display; \ No newline at end of file +pub mod display; diff --git a/src/platform_impl/linux/window.rs b/src/platform_impl/linux/window.rs index a1df150a7..a131510df 100644 --- a/src/platform_impl/linux/window.rs +++ b/src/platform_impl/linux/window.rs @@ -23,11 +23,11 @@ use crate::{ error::{ExternalError, NotSupportedError, OsError as RootOsError}, icon::Icon, monitor::MonitorHandle as RootMonitorHandle, + platform_impl::wayland::display::WlHeader, window::{ CursorIcon, Fullscreen, ProgressBarState, ResizeDirection, Theme, UserAttentionType, WindowAttributes, WindowSizeConstraints, }, - platform_impl::wayland::display::WlHeader, }; use super::{ From 8012e59d678c20d55949ac3741e1b3d01a19d29e Mon Sep 17 00:00:00 2001 From: Chooooooo Date: Mon, 23 Sep 2024 18:22:03 +0900 Subject: [PATCH 04/18] fix(window): remove non-functional logic --- src/platform_impl/linux/event_loop.rs | 4 ++-- src/platform_impl/linux/window.rs | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/platform_impl/linux/event_loop.rs b/src/platform_impl/linux/event_loop.rs index ce69fb614..5789fb20a 100644 --- a/src/platform_impl/linux/event_loop.rs +++ b/src/platform_impl/linux/event_loop.rs @@ -47,7 +47,7 @@ use super::{ }; use taskbar::TaskbarIndicator; - + #[derive(Clone)] pub struct EventLoopWindowTarget { /// Gdk display @@ -294,7 +294,7 @@ impl EventLoop { } } WindowRequest::Maximized(maximized) => { - if maximized && window.is_resizable() { + if maximized { window.maximize(); } else { window.unmaximize(); diff --git a/src/platform_impl/linux/window.rs b/src/platform_impl/linux/window.rs index a131510df..f1a5f94b8 100644 --- a/src/platform_impl/linux/window.rs +++ b/src/platform_impl/linux/window.rs @@ -109,9 +109,6 @@ impl Window { window.resize(width, height); if attributes.maximized && attributes.resizable { - if is_wayland { - window.set_resizable(true); - } window.maximize(); } From ffd9741e00e61ff95bacebf340ce0f3944a78e4d Mon Sep 17 00:00:00 2001 From: Chooooooo Date: Tue, 24 Sep 2024 18:54:36 +0900 Subject: [PATCH 05/18] feat(window): Implement window maximize process This commit introduces a new `WindowMaximizeProcess` struct that handles the step-by-step process of maximizing a window. The changes include: - Implement the `WindowMaximizeProcess` struct with methods to handle the maximize process on linux. - Update the `EventLoop` and `Window` modules to use the new `WindowMaximizeProcess` struct when handling window maximize requests. - Add a new `KeyboardInput` event handler to the `resizable.rs` example to toggle the window's maximized state. --- examples/resizable.rs | 15 ++++++++ src/platform_impl/linux/event_loop.rs | 17 +++++---- src/platform_impl/linux/util.rs | 53 ++++++++++++++++++++++++--- src/platform_impl/linux/window.rs | 17 ++++----- 4 files changed, 80 insertions(+), 22 deletions(-) diff --git a/examples/resizable.rs b/examples/resizable.rs index 617a7b4a3..029ab8739 100644 --- a/examples/resizable.rs +++ b/examples/resizable.rs @@ -16,11 +16,13 @@ fn main() { let event_loop = EventLoop::new(); let mut resizable = false; + let mut maximized = true; let window = WindowBuilder::new() .with_title("Hit space to toggle resizability.") .with_inner_size(LogicalSize::new(400.0, 200.0)) .with_resizable(resizable) + .with_maximized(maximized) .build(&event_loop) .unwrap(); @@ -43,6 +45,19 @@ fn main() { println!("Resizable: {}", resizable); window.set_resizable(resizable); } + WindowEvent::KeyboardInput { + event: + KeyEvent { + physical_key: KeyCode::Enter, + state: ElementState::Released, + .. + }, + .. + } => { + maximized = !maximized; + println!("Maximized: {}", maximized); + window.set_maximized(maximized); + } _ => (), }, _ => (), diff --git a/src/platform_impl/linux/event_loop.rs b/src/platform_impl/linux/event_loop.rs index 5789fb20a..5ebef1f1c 100644 --- a/src/platform_impl/linux/event_loop.rs +++ b/src/platform_impl/linux/event_loop.rs @@ -293,9 +293,13 @@ impl EventLoop { window.deiconify(); } } - WindowRequest::Maximized(maximized) => { + WindowRequest::Maximized(maximized, resizable) => { if maximized { - window.maximize(); + let maximize_process = util::WindowMaximizeProcess::new(window.clone(), maximized, resizable); + glib::timeout_add_local(std::time::Duration::from_millis(10), move || { + let mut maximize_process = maximize_process.borrow_mut(); + maximize_process.next_step() + }); } else { window.unmaximize(); } @@ -427,19 +431,18 @@ impl EventLoop { // Wayland add Events if is_wayland { window.connect_button_press_event(move |window, event| { + let header_bar = window.titlebar().and_downcast::().unwrap(); + let header_height = header_bar.allocated_height(); if event.button() == LMB { let (x, y) = event.root(); let (window_x, window_y) = window.position(); let (window_x, window_y) = (window_x as f64, window_y as f64); - let border_width = window.border_width() as f64; let (window_width, _) = window.size(); let window_width = window_width as f64; - if x > window_x + border_width - && x < window_x + window_width - border_width - && y > window_y + border_width - && y < window_y + border_width + TITLEBAR_HEIGHT + if x >= window_x && x <= window_x + window_width && + y >= window_y && y <= window_y + header_height as f64 { window.begin_move_drag(LMB as i32, x as i32, y as i32, event.time()); return glib::Propagation::Stop; diff --git a/src/platform_impl/linux/util.rs b/src/platform_impl/linux/util.rs index 5040a5092..571f0bbe6 100644 --- a/src/platform_impl/linux/util.rs +++ b/src/platform_impl/linux/util.rs @@ -1,15 +1,19 @@ +use crate::{ + dpi::{LogicalPosition, LogicalSize, PhysicalPosition}, + error::ExternalError, + window::WindowSizeConstraints, +}; use gtk::gdk::{ self, prelude::{DeviceExt, SeatExt}, Display, }; -use gtk::traits::{GtkWindowExt, WidgetExt}; - -use crate::{ - dpi::{LogicalPosition, LogicalSize, PhysicalPosition}, - error::ExternalError, - window::WindowSizeConstraints, +use gtk::{ + glib::{self}, + traits::{GtkWindowExt, WidgetExt}, }; +use std::cell::RefCell; +use std::rc::Rc; #[inline] pub fn cursor_position(is_wayland: bool) -> Result, ExternalError> { @@ -70,3 +74,40 @@ pub fn set_size_constraints( geom_mask, ) } + +impl WindowMaximizeProcess { + pub fn new(window: W, maximized: bool, resizable: bool) -> Rc> { + Rc::new(RefCell::new(Self { + window, + maximized, + resizable, + step: 0, + })) + } + + pub fn next_step(&mut self) -> glib::ControlFlow { + match self.step { + 0 => { + if self.maximized { + self.window.set_resizable(true); + self.step += 1; + glib::ControlFlow::Continue + } else { + self.step = 2; + glib::ControlFlow::Continue + } + } + 1 => { + self.window.maximize(); + self.step += 1; + glib::ControlFlow::Continue + } + 2 => { + self.window.set_resizable(self.resizable); + glib::ControlFlow::Break + } + _ => glib::ControlFlow::Break, + } + } +} + diff --git a/src/platform_impl/linux/window.rs b/src/platform_impl/linux/window.rs index f1a5f94b8..37ad3b12c 100644 --- a/src/platform_impl/linux/window.rs +++ b/src/platform_impl/linux/window.rs @@ -108,11 +108,12 @@ impl Window { window.set_default_size(1, 1); window.resize(width, height); - if attributes.maximized && attributes.resizable { - window.maximize(); - } + let maximize_process = util::WindowMaximizeProcess::new(window.clone(), attributes.maximized, attributes.resizable); + glib::timeout_add_local(std::time::Duration::from_millis(25), move || { + let mut maximize_process = maximize_process.borrow_mut(); + maximize_process.next_step() + }); - window.set_resizable(attributes.resizable); window.set_deletable(attributes.closable); // Set Min/Max Size @@ -576,11 +577,10 @@ impl Window { pub fn set_maximized(&self, maximized: bool) { let resizable = self.is_resizable(); - let should_maximize = maximized && resizable; if let Err(e) = self .window_requests_tx - .send((self.window_id, WindowRequest::Maximized(should_maximize))) + .send((self.window_id, WindowRequest::Maximized(maximized, resizable))) { log::warn!("Fail to send maximized request: {}", e); } @@ -603,9 +603,8 @@ impl Window { } pub fn is_maximizable(&self) -> bool { - self.window.is_resizable() && self.maximized.load(Ordering::Acquire) + true } - pub fn is_closable(&self) -> bool { self.window.is_deletable() } @@ -991,7 +990,7 @@ pub enum WindowRequest { Resizable(bool), Closable(bool), Minimized(bool), - Maximized(bool), + Maximized(bool, bool), DragWindow, DragResizeWindow(ResizeDirection), Fullscreen(Option), From d440b971edc1b283a33592c02f13c6c3ca4b633b Mon Sep 17 00:00:00 2001 From: Chooooooo Date: Tue, 24 Sep 2024 18:58:06 +0900 Subject: [PATCH 06/18] style: code format linting --- src/platform_impl/linux/event_loop.rs | 11 +++++++---- src/platform_impl/linux/util.rs | 1 - src/platform_impl/linux/window.rs | 15 ++++++++------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/platform_impl/linux/event_loop.rs b/src/platform_impl/linux/event_loop.rs index 5ebef1f1c..341f29d15 100644 --- a/src/platform_impl/linux/event_loop.rs +++ b/src/platform_impl/linux/event_loop.rs @@ -47,7 +47,7 @@ use super::{ }; use taskbar::TaskbarIndicator; - + #[derive(Clone)] pub struct EventLoopWindowTarget { /// Gdk display @@ -295,7 +295,8 @@ impl EventLoop { } WindowRequest::Maximized(maximized, resizable) => { if maximized { - let maximize_process = util::WindowMaximizeProcess::new(window.clone(), maximized, resizable); + let maximize_process = + util::WindowMaximizeProcess::new(window.clone(), maximized, resizable); glib::timeout_add_local(std::time::Duration::from_millis(10), move || { let mut maximize_process = maximize_process.borrow_mut(); maximize_process.next_step() @@ -441,8 +442,10 @@ impl EventLoop { let (window_width, _) = window.size(); let window_width = window_width as f64; - if x >= window_x && x <= window_x + window_width && - y >= window_y && y <= window_y + header_height as f64 + if x >= window_x + && x <= window_x + window_width + && y >= window_y + && y <= window_y + header_height as f64 { window.begin_move_drag(LMB as i32, x as i32, y as i32, event.time()); return glib::Propagation::Stop; diff --git a/src/platform_impl/linux/util.rs b/src/platform_impl/linux/util.rs index 571f0bbe6..442489350 100644 --- a/src/platform_impl/linux/util.rs +++ b/src/platform_impl/linux/util.rs @@ -110,4 +110,3 @@ impl WindowMaximizeProcess { } } } - diff --git a/src/platform_impl/linux/window.rs b/src/platform_impl/linux/window.rs index 37ad3b12c..d2dd70bf8 100644 --- a/src/platform_impl/linux/window.rs +++ b/src/platform_impl/linux/window.rs @@ -108,10 +108,11 @@ impl Window { window.set_default_size(1, 1); window.resize(width, height); - let maximize_process = util::WindowMaximizeProcess::new(window.clone(), attributes.maximized, attributes.resizable); + let maximize_process = + util::WindowMaximizeProcess::new(window.clone(), attributes.maximized, attributes.resizable); glib::timeout_add_local(std::time::Duration::from_millis(25), move || { - let mut maximize_process = maximize_process.borrow_mut(); - maximize_process.next_step() + let mut maximize_process = maximize_process.borrow_mut(); + maximize_process.next_step() }); window.set_deletable(attributes.closable); @@ -578,10 +579,10 @@ impl Window { pub fn set_maximized(&self, maximized: bool) { let resizable = self.is_resizable(); - if let Err(e) = self - .window_requests_tx - .send((self.window_id, WindowRequest::Maximized(maximized, resizable))) - { + if let Err(e) = self.window_requests_tx.send(( + self.window_id, + WindowRequest::Maximized(maximized, resizable), + )) { log::warn!("Fail to send maximized request: {}", e); } } From e2b1f46b9b081365afc565a13e180712c04b78bd Mon Sep 17 00:00:00 2001 From: Chooooooo Date: Tue, 24 Sep 2024 19:06:35 +0900 Subject: [PATCH 07/18] fix: restore missing struct --- src/platform_impl/linux/util.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/platform_impl/linux/util.rs b/src/platform_impl/linux/util.rs index 442489350..222833b96 100644 --- a/src/platform_impl/linux/util.rs +++ b/src/platform_impl/linux/util.rs @@ -75,6 +75,13 @@ pub fn set_size_constraints( ) } +pub struct WindowMaximizeProcess { + window: W, + maximized: bool, + resizable: bool, + step: u8, +} + impl WindowMaximizeProcess { pub fn new(window: W, maximized: bool, resizable: bool) -> Rc> { Rc::new(RefCell::new(Self { From 1717ccf10bbf8250d1c97938d8c6c25e0e300d28 Mon Sep 17 00:00:00 2001 From: Chooooooo Date: Tue, 24 Sep 2024 19:19:36 +0900 Subject: [PATCH 08/18] chore: remove unused constants --- src/platform_impl/linux/event_loop.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/platform_impl/linux/event_loop.rs b/src/platform_impl/linux/event_loop.rs index 341f29d15..1824e13e3 100644 --- a/src/platform_impl/linux/event_loop.rs +++ b/src/platform_impl/linux/event_loop.rs @@ -427,7 +427,6 @@ impl EventLoop { | EventMask::SCROLL_MASK, ); - const TITLEBAR_HEIGHT: f64 = 30.0; const LMB: u32 = 1; // Wayland add Events if is_wayland { From cd5e509d2868912fcff0c2a975f6a20481133942 Mon Sep 17 00:00:00 2001 From: Chooooooo Date: Wed, 25 Sep 2024 16:21:38 +0900 Subject: [PATCH 09/18] fix: Revert resizable and add a flag to window_debug --- examples/resizable.rs | 15 --------------- examples/window_debug.rs | 7 +++++++ 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/examples/resizable.rs b/examples/resizable.rs index 029ab8739..617a7b4a3 100644 --- a/examples/resizable.rs +++ b/examples/resizable.rs @@ -16,13 +16,11 @@ fn main() { let event_loop = EventLoop::new(); let mut resizable = false; - let mut maximized = true; let window = WindowBuilder::new() .with_title("Hit space to toggle resizability.") .with_inner_size(LogicalSize::new(400.0, 200.0)) .with_resizable(resizable) - .with_maximized(maximized) .build(&event_loop) .unwrap(); @@ -45,19 +43,6 @@ fn main() { println!("Resizable: {}", resizable); window.set_resizable(resizable); } - WindowEvent::KeyboardInput { - event: - KeyEvent { - physical_key: KeyCode::Enter, - state: ElementState::Released, - .. - }, - .. - } => { - maximized = !maximized; - println!("Maximized: {}", maximized); - window.set_maximized(maximized); - } _ => (), }, _ => (), diff --git a/examples/window_debug.rs b/examples/window_debug.rs index 461295146..f65002bbe 100644 --- a/examples/window_debug.rs +++ b/examples/window_debug.rs @@ -33,6 +33,7 @@ fn main() { eprintln!(" (T) Toggle always on top"); eprintln!(" (B) Toggle always on bottom"); eprintln!(" (C) Toggle content protection"); + eprintln!(" (R) Toggle resizable"); eprintln!(" (M) Toggle minimized"); eprintln!(" (X) Toggle maximized"); eprintln!(" (Q) Quit event loop"); @@ -44,6 +45,7 @@ fn main() { let mut always_on_top = false; let mut visible = true; let mut content_protection = false; + let mut resizable = false; event_loop.run(move |event, _, control_flow| { *control_flow = ControlFlow::Wait; @@ -119,6 +121,11 @@ fn main() { window.set_fullscreen(Some(Fullscreen::Borderless(None))); } } + "r" => { + resizable = !resizable; + window.set_resizable(resizable); + println!("Resizable: {}", resizable); + } "m" => { window.set_minimized(!window.is_minimized()); } From 968e49103eb3141cab77b6aa99ae2d93505526c9 Mon Sep 17 00:00:00 2001 From: Chooooooo Date: Wed, 25 Sep 2024 16:33:13 +0900 Subject: [PATCH 10/18] rename: `display` to `header` in wayland --- src/platform_impl/linux/wayland/{display.rs => header.rs} | 0 src/platform_impl/linux/wayland/mod.rs | 2 +- src/platform_impl/linux/window.rs | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename src/platform_impl/linux/wayland/{display.rs => header.rs} (100%) diff --git a/src/platform_impl/linux/wayland/display.rs b/src/platform_impl/linux/wayland/header.rs similarity index 100% rename from src/platform_impl/linux/wayland/display.rs rename to src/platform_impl/linux/wayland/header.rs diff --git a/src/platform_impl/linux/wayland/mod.rs b/src/platform_impl/linux/wayland/mod.rs index d80d8181a..a200d2603 100644 --- a/src/platform_impl/linux/wayland/mod.rs +++ b/src/platform_impl/linux/wayland/mod.rs @@ -2,4 +2,4 @@ // Copyright 2021-2023 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 -pub mod display; +pub mod header; diff --git a/src/platform_impl/linux/window.rs b/src/platform_impl/linux/window.rs index d2dd70bf8..4d1ed2388 100644 --- a/src/platform_impl/linux/window.rs +++ b/src/platform_impl/linux/window.rs @@ -23,7 +23,7 @@ use crate::{ error::{ExternalError, NotSupportedError, OsError as RootOsError}, icon::Icon, monitor::MonitorHandle as RootMonitorHandle, - platform_impl::wayland::display::WlHeader, + platform_impl::wayland::header::WlHeader, window::{ CursorIcon, Fullscreen, ProgressBarState, ResizeDirection, Theme, UserAttentionType, WindowAttributes, WindowSizeConstraints, From 832518326483d3f173b7caea9a9a3100b556e0be Mon Sep 17 00:00:00 2001 From: Chooooooo Date: Wed, 25 Sep 2024 21:18:02 +0900 Subject: [PATCH 11/18] feat(event-loop): Improve window button handling The changes in this commit focus on improving the handling of window button events on Linux platforms. The key changes are: 1. Moved the `LMB` constant declaration to the correct location to avoid duplicating it. 2. Removed the Wayland-specific button press event handling, as it was redundant and not necessary. 3. Simplified the window button event handling by removing the unnecessary logic related to Wayland-specific header bar handling. These changes help to simplify the event loop implementation and make the code more maintainable. --- src/platform_impl/linux/event_loop.rs | 31 +----- src/platform_impl/linux/wayland/header.rs | 113 ++++++---------------- src/platform_impl/linux/window.rs | 2 +- 3 files changed, 30 insertions(+), 116 deletions(-) diff --git a/src/platform_impl/linux/event_loop.rs b/src/platform_impl/linux/event_loop.rs index 1824e13e3..45511507f 100644 --- a/src/platform_impl/linux/event_loop.rs +++ b/src/platform_impl/linux/event_loop.rs @@ -262,7 +262,6 @@ impl EventLoop { }; let mut taskbar = TaskbarIndicator::new(); - let is_wayland = window_target.is_wayland(); // Window Request window_requests_rx.attach(Some(&context), move |(id, request)| { @@ -297,7 +296,7 @@ impl EventLoop { if maximized { let maximize_process = util::WindowMaximizeProcess::new(window.clone(), maximized, resizable); - glib::timeout_add_local(std::time::Duration::from_millis(10), move || { + glib::idle_add_local_full(glib::Priority::DEFAULT_IDLE, move || { let mut maximize_process = maximize_process.borrow_mut(); maximize_process.next_step() }); @@ -427,33 +426,6 @@ impl EventLoop { | EventMask::SCROLL_MASK, ); - const LMB: u32 = 1; - // Wayland add Events - if is_wayland { - window.connect_button_press_event(move |window, event| { - let header_bar = window.titlebar().and_downcast::().unwrap(); - let header_height = header_bar.allocated_height(); - if event.button() == LMB { - let (x, y) = event.root(); - let (window_x, window_y) = window.position(); - let (window_x, window_y) = (window_x as f64, window_y as f64); - - let (window_width, _) = window.size(); - let window_width = window_width as f64; - - if x >= window_x - && x <= window_x + window_width - && y >= window_y - && y <= window_y + header_height as f64 - { - window.begin_move_drag(LMB as i32, x as i32, y as i32, event.time()); - return glib::Propagation::Stop; - } - } - glib::Propagation::Proceed - }); - } - let fullscreen = Rc::new(AtomicBool::new(fullscreen)); let fullscreen_ = fullscreen.clone(); window.connect_window_state_event(move |_window, event| { @@ -495,6 +467,7 @@ impl EventLoop { glib::Propagation::Proceed }); window.connect_button_press_event(move |window, event| { + const LMB: u32 = 1; if event.button() == LMB { let (cx, cy) = event.root(); let (left, top) = window.position(); diff --git a/src/platform_impl/linux/wayland/header.rs b/src/platform_impl/linux/wayland/header.rs index f35ef0063..8b40dcde8 100644 --- a/src/platform_impl/linux/wayland/header.rs +++ b/src/platform_impl/linux/wayland/header.rs @@ -1,103 +1,44 @@ use gtk::{ - gdk::{self}, glib::{self}, prelude::*, - ApplicationWindow, Button, HeaderBar, Image, ToggleButton, + ApplicationWindow, HeaderBar, }; + pub struct WlHeader; impl WlHeader { pub fn setup(window: &ApplicationWindow) { - let header = HeaderBar::new(); - header.set_show_close_button(false); - - let close_button = Self::create_header_button("window-close-symbolic"); - let maximize_button = Self::create_header_toggle_button("window-maximize-symbolic"); - let minimize_button = Self::create_header_button("window-minimize-symbolic"); - - Self::connect_close_button(close_button.clone(), window); - Self::connect_maximize_button(maximize_button.clone(), window); - Self::connect_minimize_button(minimize_button.clone(), window); - - header.pack_end(&close_button); - header.pack_end(&maximize_button); - header.pack_end(&minimize_button); + let header = HeaderBar::builder() + .show_close_button(true) + .decoration_layout("menu:minimize,maximize,close") + .build(); window.set_titlebar(Some(&header)); + Self::connect_move_window(&header, &window); } - fn create_header_button(icon_name: &str) -> Button { - let button = Button::new(); - let icon = Image::from_icon_name(Some(icon_name), gtk::IconSize::Button); - button.set_image(Some(&icon)); - button - } - - fn create_header_toggle_button(icon_name: &str) -> ToggleButton { - let button = ToggleButton::new(); - let icon = Image::from_icon_name(Some(icon_name), gtk::IconSize::Button); - button.set_image(Some(&icon)); - button - } - - fn connect_close_button(button: Button, window: &ApplicationWindow) { - let window_weak = window.downgrade(); - button.connect_clicked(move |_| { - if let Some(window) = window_weak.upgrade() { - window.close(); - } - }); - } - - fn connect_maximize_button(button: ToggleButton, window: &ApplicationWindow) { - let window_weak = window.downgrade(); - // initial state - if let Some(window) = window_weak.upgrade() { - button.set_active(window.is_maximized()); - button.set_sensitive(window.is_resizable()); - } - - let button_weak = button.downgrade(); - window.connect_is_maximized_notify(move |window| { - if let Some(button) = button_weak.upgrade() { - button.set_active(window.is_maximized()); - } - }); - - let button_weak = button.downgrade(); - window.connect_resizable_notify(move |window| { - if let Some(button) = button_weak.upgrade() { - button.set_sensitive(window.is_resizable()); - } - }); - - //click event - button.connect_toggled(move |button| { - if let Some(window) = window_weak.upgrade() { - if button.is_active() && window.is_resizable() { - window.maximize(); - } else { - window.unmaximize(); + fn connect_move_window(header: &HeaderBar, window: &ApplicationWindow) { + let header_weak = header.downgrade(); + window.connect_button_press_event(move |window, event| { + const LMB: u32 = 1; + if event.button() == LMB { + if let Some(header) = header_weak.upgrade() { + let header_height = header.allocated_height(); + let (x, y) = event.root(); + let (window_x, window_y) = window.position(); + let (window_width, _) = window.size(); + + if x >= window_x as f64 + && x <= (window_x + window_width) as f64 + && y >= window_y as f64 + && y <= (window_y + header_height) as f64 + { + window.begin_move_drag(LMB as i32, x as i32, y as i32, event.time()); + return glib::Propagation::Stop; + } } } - }); - - // Prevent space key activation in header - button.connect_key_press_event(move |_, event_key| { - if event_key.keyval() == gdk::keys::constants::space { - glib::Propagation::Stop - } else { - glib::Propagation::Proceed - } - }); - } - - fn connect_minimize_button(button: Button, window: &ApplicationWindow) { - let window_weak = window.downgrade(); - button.connect_clicked(move |_| { - if let Some(window) = window_weak.upgrade() { - window.iconify(); - } + glib::Propagation::Proceed }); } } diff --git a/src/platform_impl/linux/window.rs b/src/platform_impl/linux/window.rs index 4d1ed2388..459a13637 100644 --- a/src/platform_impl/linux/window.rs +++ b/src/platform_impl/linux/window.rs @@ -110,7 +110,7 @@ impl Window { let maximize_process = util::WindowMaximizeProcess::new(window.clone(), attributes.maximized, attributes.resizable); - glib::timeout_add_local(std::time::Duration::from_millis(25), move || { + glib::idle_add_local_full(glib::Priority::HIGH_IDLE, move || { let mut maximize_process = maximize_process.borrow_mut(); maximize_process.next_step() }); From 5d8d78d02f4cd1486664c7b1479795af55b1603e Mon Sep 17 00:00:00 2001 From: Chooooooo Date: Thu, 26 Sep 2024 16:34:06 +0900 Subject: [PATCH 12/18] feat(window): update window dragging on Wayland --- src/platform_impl/linux/event_loop.rs | 7 ++++- src/platform_impl/linux/wayland/header.rs | 37 +++++++++++------------ src/platform_impl/linux/window.rs | 2 +- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/platform_impl/linux/event_loop.rs b/src/platform_impl/linux/event_loop.rs index 45511507f..983c38658 100644 --- a/src/platform_impl/linux/event_loop.rs +++ b/src/platform_impl/linux/event_loop.rs @@ -262,6 +262,7 @@ impl EventLoop { }; let mut taskbar = TaskbarIndicator::new(); + let is_wayland = window_target.is_wayland(); // Window Request window_requests_rx.attach(Some(&context), move |(id, request)| { @@ -468,7 +469,11 @@ impl EventLoop { }); window.connect_button_press_event(move |window, event| { const LMB: u32 = 1; - if event.button() == LMB { + if (is_wayland && window.is_decorated()) + && window.is_resizable() + && !window.is_maximized() + && event.button() == LMB + { let (cx, cy) = event.root(); let (left, top) = window.position(); let (w, h) = window.size(); diff --git a/src/platform_impl/linux/wayland/header.rs b/src/platform_impl/linux/wayland/header.rs index 8b40dcde8..507ea900d 100644 --- a/src/platform_impl/linux/wayland/header.rs +++ b/src/platform_impl/linux/wayland/header.rs @@ -1,41 +1,38 @@ use gtk::{ glib::{self}, prelude::*, - ApplicationWindow, HeaderBar, + ApplicationWindow, EventBox, HeaderBar, }; pub struct WlHeader; impl WlHeader { - pub fn setup(window: &ApplicationWindow) { + pub fn setup(window: &ApplicationWindow, title: &str) { let header = HeaderBar::builder() .show_close_button(true) .decoration_layout("menu:minimize,maximize,close") + .title(title) .build(); - window.set_titlebar(Some(&header)); - Self::connect_move_window(&header, &window); + let event_box = EventBox::new(); + event_box.set_above_child(true); + event_box.set_visible(true); + event_box.set_can_focus(false); + event_box.add(&header); + + window.set_titlebar(Some(&event_box)); + Self::connect_move_window(&event_box, &window); } - fn connect_move_window(header: &HeaderBar, window: &ApplicationWindow) { - let header_weak = header.downgrade(); - window.connect_button_press_event(move |window, event| { + fn connect_move_window(event_box: &EventBox, window: &ApplicationWindow) { + let window_weak = window.downgrade(); + event_box.connect_button_press_event(move |_, event| { const LMB: u32 = 1; if event.button() == LMB { - if let Some(header) = header_weak.upgrade() { - let header_height = header.allocated_height(); + if let Some(window) = window_weak.upgrade() { let (x, y) = event.root(); - let (window_x, window_y) = window.position(); - let (window_width, _) = window.size(); - - if x >= window_x as f64 - && x <= (window_x + window_width) as f64 - && y >= window_y as f64 - && y <= (window_y + header_height) as f64 - { - window.begin_move_drag(LMB as i32, x as i32, y as i32, event.time()); - return glib::Propagation::Stop; - } + window.begin_move_drag(LMB as i32, x as i32, y as i32, event.time()); + return glib::Propagation::Stop; } } glib::Propagation::Proceed diff --git a/src/platform_impl/linux/window.rs b/src/platform_impl/linux/window.rs index 459a13637..b5ced655d 100644 --- a/src/platform_impl/linux/window.rs +++ b/src/platform_impl/linux/window.rs @@ -90,7 +90,7 @@ impl Window { let window = window_builder.build(); if is_wayland { - WlHeader::setup(&window); + WlHeader::setup(&window, &attributes.title); } let window_id = WindowId(window.id()); From 0e842847daf73f2f6a006a186763ba642975472d Mon Sep 17 00:00:00 2001 From: Chooooooo Date: Thu, 26 Sep 2024 19:04:40 +0900 Subject: [PATCH 13/18] feat(wayland): update header button event --- src/platform_impl/linux/wayland/header.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/platform_impl/linux/wayland/header.rs b/src/platform_impl/linux/wayland/header.rs index 507ea900d..70bd802b2 100644 --- a/src/platform_impl/linux/wayland/header.rs +++ b/src/platform_impl/linux/wayland/header.rs @@ -22,6 +22,7 @@ impl WlHeader { window.set_titlebar(Some(&event_box)); Self::connect_move_window(&event_box, &window); + Self::connect_resize_window(&header, window); } fn connect_move_window(event_box: &EventBox, window: &ApplicationWindow) { @@ -38,4 +39,18 @@ impl WlHeader { glib::Propagation::Proceed }); } + + fn connect_resize_window(header: &HeaderBar, window: &ApplicationWindow) { + let header_weak = header.downgrade(); + window.connect_resizable_notify(move |window| { + if let Some(header) = header_weak.upgrade() { + let is_resizable = window.is_resizable(); + header.set_decoration_layout(if !is_resizable { + Some("menu:minimize,close") + } else { + Some("menu:minimize,maximize,close") + }); + } + }); + } } From a3ce8dc150a3194c3a2242914d13b426c9f86e52 Mon Sep 17 00:00:00 2001 From: Chooooooo Date: Thu, 26 Sep 2024 22:17:49 +0900 Subject: [PATCH 14/18] feat: update dragging functionality for Wayland windows --- src/platform_impl/linux/wayland/header.rs | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/platform_impl/linux/wayland/header.rs b/src/platform_impl/linux/wayland/header.rs index 70bd802b2..9ed3dcc49 100644 --- a/src/platform_impl/linux/wayland/header.rs +++ b/src/platform_impl/linux/wayland/header.rs @@ -1,7 +1,6 @@ use gtk::{ - glib::{self}, prelude::*, - ApplicationWindow, EventBox, HeaderBar, + ApplicationWindow, EventBox, HeaderBar }; pub struct WlHeader; @@ -21,25 +20,9 @@ impl WlHeader { event_box.add(&header); window.set_titlebar(Some(&event_box)); - Self::connect_move_window(&event_box, &window); Self::connect_resize_window(&header, window); } - fn connect_move_window(event_box: &EventBox, window: &ApplicationWindow) { - let window_weak = window.downgrade(); - event_box.connect_button_press_event(move |_, event| { - const LMB: u32 = 1; - if event.button() == LMB { - if let Some(window) = window_weak.upgrade() { - let (x, y) = event.root(); - window.begin_move_drag(LMB as i32, x as i32, y as i32, event.time()); - return glib::Propagation::Stop; - } - } - glib::Propagation::Proceed - }); - } - fn connect_resize_window(header: &HeaderBar, window: &ApplicationWindow) { let header_weak = header.downgrade(); window.connect_resizable_notify(move |window| { From 67330c44992e3279319e6a7739e79cfb0dd1b013 Mon Sep 17 00:00:00 2001 From: Chooooooo Date: Thu, 26 Sep 2024 22:44:26 +0900 Subject: [PATCH 15/18] chore: add changes to `.changes` file. --- .changes/improve-wayland-display.md | 11 +++++++++++ src/platform_impl/linux/wayland/header.rs | 5 +---- 2 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 .changes/improve-wayland-display.md diff --git a/.changes/improve-wayland-display.md b/.changes/improve-wayland-display.md new file mode 100644 index 000000000..4d504711c --- /dev/null +++ b/.changes/improve-wayland-display.md @@ -0,0 +1,11 @@ +--- +"tao": patch +--- + +Changed the event handling for maximizing to process events sequentially to avoid "Error 71(Protocol error): dispatching to Wayland display". + +Added buttons for maximize and minimize in the Wayland title bar. + +Fixed an issue where the window was not resizing when dragging the window borders. + +Fixed an issue where the window was not moving when dragging the header bar area. diff --git a/src/platform_impl/linux/wayland/header.rs b/src/platform_impl/linux/wayland/header.rs index 9ed3dcc49..480eb4c85 100644 --- a/src/platform_impl/linux/wayland/header.rs +++ b/src/platform_impl/linux/wayland/header.rs @@ -1,7 +1,4 @@ -use gtk::{ - prelude::*, - ApplicationWindow, EventBox, HeaderBar -}; +use gtk::{prelude::*, ApplicationWindow, EventBox, HeaderBar}; pub struct WlHeader; From 64fe0016d664ab2be41e558aea79b648f55f875a Mon Sep 17 00:00:00 2001 From: Chooooooo Date: Fri, 27 Sep 2024 02:39:54 +0900 Subject: [PATCH 16/18] fix: update code formatting --- .changes/improve-wayland-display.md | 8 +------- .changes/wayland-dragging-header.md | 5 +++++ .changes/wayland-resize-window.md | 5 +++++ .changes/wayland-titlebar.md | 5 +++++ src/platform_impl/linux/event_loop.rs | 2 +- src/platform_impl/linux/util.rs | 1 + src/platform_impl/linux/window.rs | 19 +++++++++++++------ 7 files changed, 31 insertions(+), 14 deletions(-) create mode 100644 .changes/wayland-dragging-header.md create mode 100644 .changes/wayland-resize-window.md create mode 100644 .changes/wayland-titlebar.md diff --git a/.changes/improve-wayland-display.md b/.changes/improve-wayland-display.md index 4d504711c..cf6eb7c08 100644 --- a/.changes/improve-wayland-display.md +++ b/.changes/improve-wayland-display.md @@ -2,10 +2,4 @@ "tao": patch --- -Changed the event handling for maximizing to process events sequentially to avoid "Error 71(Protocol error): dispatching to Wayland display". - -Added buttons for maximize and minimize in the Wayland title bar. - -Fixed an issue where the window was not resizing when dragging the window borders. - -Fixed an issue where the window was not moving when dragging the header bar area. +On Linux Wayland, changed the event handling for maximizing to process events sequentially to avoid "Error 71(Protocol error): dispatching to Wayland display". diff --git a/.changes/wayland-dragging-header.md b/.changes/wayland-dragging-header.md new file mode 100644 index 000000000..348acafa3 --- /dev/null +++ b/.changes/wayland-dragging-header.md @@ -0,0 +1,5 @@ +--- +"tao": patch +--- + +On Linux Wayland, fixed an issue where the window was not moving when dragging the header bar area. \ No newline at end of file diff --git a/.changes/wayland-resize-window.md b/.changes/wayland-resize-window.md new file mode 100644 index 000000000..0f749e8f1 --- /dev/null +++ b/.changes/wayland-resize-window.md @@ -0,0 +1,5 @@ +--- +"tao": patch +--- + +On Linux Wayland, fixed an issue where the window was not resizing when dragging the window borders. \ No newline at end of file diff --git a/.changes/wayland-titlebar.md b/.changes/wayland-titlebar.md new file mode 100644 index 000000000..21b56871b --- /dev/null +++ b/.changes/wayland-titlebar.md @@ -0,0 +1,5 @@ +--- +"tao": patch +--- + +On Linux Wayland, added buttons for maximize and minimize in the title bar. diff --git a/src/platform_impl/linux/event_loop.rs b/src/platform_impl/linux/event_loop.rs index 983c38658..60401e40c 100644 --- a/src/platform_impl/linux/event_loop.rs +++ b/src/platform_impl/linux/event_loop.rs @@ -469,7 +469,7 @@ impl EventLoop { }); window.connect_button_press_event(move |window, event| { const LMB: u32 = 1; - if (is_wayland && window.is_decorated()) + if (is_wayland || !window.is_decorated()) && window.is_resizable() && !window.is_maximized() && event.button() == LMB diff --git a/src/platform_impl/linux/util.rs b/src/platform_impl/linux/util.rs index 222833b96..af6699d9d 100644 --- a/src/platform_impl/linux/util.rs +++ b/src/platform_impl/linux/util.rs @@ -100,6 +100,7 @@ impl WindowMaximizeProcess { self.step += 1; glib::ControlFlow::Continue } else { + //It should still revert to the previous resizable state. self.step = 2; glib::ControlFlow::Continue } diff --git a/src/platform_impl/linux/window.rs b/src/platform_impl/linux/window.rs index b5ced655d..84c3022e9 100644 --- a/src/platform_impl/linux/window.rs +++ b/src/platform_impl/linux/window.rs @@ -108,12 +108,19 @@ impl Window { window.set_default_size(1, 1); window.resize(width, height); - let maximize_process = - util::WindowMaximizeProcess::new(window.clone(), attributes.maximized, attributes.resizable); - glib::idle_add_local_full(glib::Priority::HIGH_IDLE, move || { - let mut maximize_process = maximize_process.borrow_mut(); - maximize_process.next_step() - }); + if attributes.maximized { + let maximize_process = util::WindowMaximizeProcess::new( + window.clone(), + attributes.maximized, + attributes.resizable, + ); + glib::idle_add_local_full(glib::Priority::HIGH_IDLE, move || { + let mut maximize_process = maximize_process.borrow_mut(); + maximize_process.next_step() + }); + } else { + window.set_resizable(attributes.resizable); + } window.set_deletable(attributes.closable); From baa68777bf84700cd57c10464d91904f3e5404bd Mon Sep 17 00:00:00 2001 From: Chooooooo Date: Fri, 27 Sep 2024 03:37:54 +0900 Subject: [PATCH 17/18] fix: update Wayland maximize process condition --- src/platform_impl/linux/event_loop.rs | 2 +- src/platform_impl/linux/util.rs | 16 ++++------------ src/platform_impl/linux/window.rs | 1 - 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/src/platform_impl/linux/event_loop.rs b/src/platform_impl/linux/event_loop.rs index 60401e40c..3e3b5f52c 100644 --- a/src/platform_impl/linux/event_loop.rs +++ b/src/platform_impl/linux/event_loop.rs @@ -296,7 +296,7 @@ impl EventLoop { WindowRequest::Maximized(maximized, resizable) => { if maximized { let maximize_process = - util::WindowMaximizeProcess::new(window.clone(), maximized, resizable); + util::WindowMaximizeProcess::new(window.clone(), resizable); glib::idle_add_local_full(glib::Priority::DEFAULT_IDLE, move || { let mut maximize_process = maximize_process.borrow_mut(); maximize_process.next_step() diff --git a/src/platform_impl/linux/util.rs b/src/platform_impl/linux/util.rs index af6699d9d..393932c08 100644 --- a/src/platform_impl/linux/util.rs +++ b/src/platform_impl/linux/util.rs @@ -77,16 +77,14 @@ pub fn set_size_constraints( pub struct WindowMaximizeProcess { window: W, - maximized: bool, resizable: bool, step: u8, } impl WindowMaximizeProcess { - pub fn new(window: W, maximized: bool, resizable: bool) -> Rc> { + pub fn new(window: W, resizable: bool) -> Rc> { Rc::new(RefCell::new(Self { window, - maximized, resizable, step: 0, })) @@ -95,15 +93,9 @@ impl WindowMaximizeProcess { pub fn next_step(&mut self) -> glib::ControlFlow { match self.step { 0 => { - if self.maximized { - self.window.set_resizable(true); - self.step += 1; - glib::ControlFlow::Continue - } else { - //It should still revert to the previous resizable state. - self.step = 2; - glib::ControlFlow::Continue - } + self.window.set_resizable(true); + self.step += 1; + glib::ControlFlow::Continue } 1 => { self.window.maximize(); diff --git a/src/platform_impl/linux/window.rs b/src/platform_impl/linux/window.rs index 05bd94560..8813051cf 100644 --- a/src/platform_impl/linux/window.rs +++ b/src/platform_impl/linux/window.rs @@ -112,7 +112,6 @@ impl Window { if attributes.maximized { let maximize_process = util::WindowMaximizeProcess::new( window.clone(), - attributes.maximized, attributes.resizable, ); glib::idle_add_local_full(glib::Priority::HIGH_IDLE, move || { From 9703609f5ba056e9316c920a00773d6cd8b13b8e Mon Sep 17 00:00:00 2001 From: Chooooooo Date: Fri, 27 Sep 2024 03:50:18 +0900 Subject: [PATCH 18/18] chore:code format linting --- src/platform_impl/linux/event_loop.rs | 3 +-- src/platform_impl/linux/window.rs | 5 +---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/platform_impl/linux/event_loop.rs b/src/platform_impl/linux/event_loop.rs index 3e3b5f52c..d5ce7e21b 100644 --- a/src/platform_impl/linux/event_loop.rs +++ b/src/platform_impl/linux/event_loop.rs @@ -295,8 +295,7 @@ impl EventLoop { } WindowRequest::Maximized(maximized, resizable) => { if maximized { - let maximize_process = - util::WindowMaximizeProcess::new(window.clone(), resizable); + let maximize_process = util::WindowMaximizeProcess::new(window.clone(), resizable); glib::idle_add_local_full(glib::Priority::DEFAULT_IDLE, move || { let mut maximize_process = maximize_process.borrow_mut(); maximize_process.next_step() diff --git a/src/platform_impl/linux/window.rs b/src/platform_impl/linux/window.rs index 8813051cf..5d988e93a 100644 --- a/src/platform_impl/linux/window.rs +++ b/src/platform_impl/linux/window.rs @@ -110,10 +110,7 @@ impl Window { window.resize(width, height); if attributes.maximized { - let maximize_process = util::WindowMaximizeProcess::new( - window.clone(), - attributes.resizable, - ); + let maximize_process = util::WindowMaximizeProcess::new(window.clone(), attributes.resizable); glib::idle_add_local_full(glib::Priority::HIGH_IDLE, move || { let mut maximize_process = maximize_process.borrow_mut(); maximize_process.next_step()