diff --git a/.changes/wayland-inner-size.md b/.changes/wayland-inner-size.md new file mode 100644 index 000000000..1596a731d --- /dev/null +++ b/.changes/wayland-inner-size.md @@ -0,0 +1,5 @@ +--- +"tao": patch +--- + +On Linux Wayland, fixed the inaccurately applied `inner_size` when creating a new window. \ No newline at end of file diff --git a/src/platform_impl/linux/event_loop.rs b/src/platform_impl/linux/event_loop.rs index e39ee9f19..b35944bb8 100644 --- a/src/platform_impl/linux/event_loop.rs +++ b/src/platform_impl/linux/event_loop.rs @@ -603,7 +603,13 @@ impl EventLoop { log::warn!("Failed to send window moved event to event channel: {}", e); } - let (w, h) = event.size(); + let (w, h) = if let Some(child) = window.child() { + let allocation = child.allocation(); + (allocation.width() as u32, allocation.height() as u32) + } else { + event.size() + }; + if let Err(e) = tx_clone.send(Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::Resized( diff --git a/src/platform_impl/linux/wayland/header.rs b/src/platform_impl/linux/wayland/header.rs index 480eb4c85..343034f3f 100644 --- a/src/platform_impl/linux/wayland/header.rs +++ b/src/platform_impl/linux/wayland/header.rs @@ -1,25 +1,62 @@ -use gtk::{prelude::*, ApplicationWindow, EventBox, HeaderBar}; +use gtk::{ + glib::{self}, + pango, + prelude::*, + Align, ApplicationWindow, EventBox, HeaderBar, Label, +}; pub struct WlHeader; impl WlHeader { - pub fn setup(window: &ApplicationWindow, title: &str) { + pub fn setup(window: &ApplicationWindow, title: &str, min_width: i32) { let header = HeaderBar::builder() .show_close_button(true) .decoration_layout("menu:minimize,maximize,close") - .title(title) .build(); + let title_label = Label::new(Some(title)); + title_label.set_ellipsize(gtk::pango::EllipsizeMode::End); + title_label.set_single_line_mode(true); + title_label.set_halign(Align::Center); + 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); + let header_clone = header.clone(); + let event_box_clone = event_box.clone(); + glib::idle_add_local_full(glib::Priority::HIGH_IDLE, move || { + let allocated_height = header_clone.allocated_height(); + event_box_clone.set_size_request(min_width, allocated_height); + header_clone.set_size_request(min_width, allocated_height); + glib::ControlFlow::Break + }); + + header.set_custom_title(Some(&title_label)); + event_box.add(&header); window.set_titlebar(Some(&event_box)); + + //Set title font width + let context = title_label.pango_context(); + let font_description = context.font_description().unwrap(); + let font_size = (font_description.size() / pango::SCALE) as f64; + let char_width = font_size * 2.0; + + Self::connect_configure_event(window, &title_label, char_width); Self::connect_resize_window(&header, window); } + fn connect_configure_event(window: &ApplicationWindow, title_label: &Label, char_width: f64) { + let title_label_clone = title_label.clone(); + window.connect_configure_event(move |_, event| { + let (width, _) = event.size(); + let max_chars = (width as f64 / char_width).floor() as i32; + title_label_clone.set_max_width_chars(if width < 220 { 0 } else { max_chars }); + false + }); + } + fn connect_resize_window(header: &HeaderBar, window: &ApplicationWindow) { let header_weak = header.downgrade(); window.connect_resizable_notify(move |window| { diff --git a/src/platform_impl/linux/window.rs b/src/platform_impl/linux/window.rs index 08c53a12e..f1306b164 100644 --- a/src/platform_impl/linux/window.rs +++ b/src/platform_impl/linux/window.rs @@ -93,9 +93,15 @@ impl Window { } let window = window_builder.build(); + let win_scale_factor = window.scale_factor(); + let min_inner_size = attributes + .inner_size_constraints + .min_size_physical::(win_scale_factor as f64); + let min_width = min_inner_size.width.max(1); + let min_height = min_inner_size.height.max(1); if is_wayland { - WlHeader::setup(&window, &attributes.title); + WlHeader::setup(&window, &attributes.title, min_width); } let window_id = WindowId(window.id()); @@ -105,13 +111,17 @@ impl Window { .insert(window_id); // Set Width/Height & Resizable - let win_scale_factor = window.scale_factor(); let (width, height) = attributes .inner_size .map(|size| size.to_logical::(win_scale_factor as f64).into()) .unwrap_or((800, 600)); - window.set_default_size(1, 1); - window.resize(width, height); + + let window_clone = window.clone(); + glib::idle_add_local_full(glib::Priority::HIGH_IDLE, move || { + window_clone.set_default_size(min_width, min_height); + window_clone.resize(width, height); + glib::ControlFlow::Break + }); if attributes.maximized { let maximize_process = util::WindowMaximizeProcess::new(window.clone(), attributes.resizable); @@ -128,6 +138,15 @@ impl Window { // Set Min/Max Size util::set_size_constraints(&window, attributes.inner_size_constraints); + let default_vbox = if pl_attribs.default_vbox { + let box_ = gtk::Box::new(gtk::Orientation::Vertical, 0); + box_.set_size_request(min_width, min_height); + window.add(&box_); + Some(box_) + } else { + None + }; + // Set Position if let Some(position) = attributes.position { let (x, y): (i32, i32) = position.to_logical::(win_scale_factor as f64).into(); @@ -159,14 +178,6 @@ impl Window { } } - let default_vbox = if pl_attribs.default_vbox { - let box_ = gtk::Box::new(gtk::Orientation::Vertical, 0); - window.add(&box_); - Some(box_) - } else { - None - }; - // Rest attributes window.set_title(&attributes.title); if let Some(Fullscreen::Borderless(m)) = &attributes.fullscreen {