From 3a2443c859d056a7e1db24ea95ab96fffe2b69c1 Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 3 Aug 2026 23:26:51 -0400 Subject: [PATCH] fix: replace GTK4 ColorDialogButton popovers with custom GTK buttons that spawn full native ColorDialog windows to avoid unresizing popovers --- src/ui/editor.rs | 87 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 27 deletions(-) diff --git a/src/ui/editor.rs b/src/ui/editor.rs index b23173d..e904cf2 100644 --- a/src/ui/editor.rs +++ b/src/ui/editor.rs @@ -1,7 +1,7 @@ use crate::composite_icon::CompositeIcon; use gtk::prelude::*; use gtk::{ - Box as GtkBox, ColorDialog, ColorDialogButton, Label, Orientation, Picture, ScrolledWindow, + Box as GtkBox, ColorDialog, Label, Orientation, Picture, ScrolledWindow, }; use std::cell::RefCell; use std::rc::Rc; @@ -209,38 +209,71 @@ pub fn build_editor_page( label.set_xalign(0.0); let rgba = gtk::gdk::RGBA::parse(&hex).unwrap_or(gtk::gdk::RGBA::BLACK); - let dialog = ColorDialog::builder().build(); - let button = ColorDialogButton::new(Some(dialog)); - button.set_rgba(&rgba); + let current_rgba = Rc::new(RefCell::new(rgba)); + + let drawing_area = gtk::DrawingArea::new(); + drawing_area.set_size_request(40, 24); + { + let current_rgba = Rc::clone(¤t_rgba); + drawing_area.set_draw_func(move |_, cr, width, height| { + let c = current_rgba.borrow(); + cr.set_source_rgba(c.red() as f64, c.green() as f64, c.blue() as f64, 1.0); + cr.rectangle(0.0, 0.0, width as f64, height as f64); + cr.fill().expect("fill"); + }); + } + + let button = gtk::Button::builder() + .child(&drawing_area) + .build(); + + let dialog = ColorDialog::builder().title("Pick a Color").build(); { let composite = Rc::clone(&composite); let tag = tag.clone(); let refresh_preview = refresh_preview.clone(); - button.connect_rgba_notify(move |btn| { - let new_rgba = btn.rgba(); - let new_hex = format!( - "#{:02x}{:02x}{:02x}", - (new_rgba.red() * 255.0).round() as u8, - (new_rgba.green() * 255.0).round() as u8, - (new_rgba.blue() * 255.0).round() as u8, - ); - let changed = { - let mut comp = composite.borrow_mut(); - let res; - if is_emblem { - res = comp.emblem.as_mut().unwrap().update_color(&tag, &new_hex).unwrap_or(false); - } else { - res = comp.bg.update_color(&tag, &new_hex).unwrap_or(false); + let current_rgba = Rc::clone(¤t_rgba); + let drawing_area = drawing_area.clone(); + + button.connect_clicked(move |btn| { + let dialog = dialog.clone(); + let tag = tag.clone(); + let composite = Rc::clone(&composite); + let refresh_preview = refresh_preview.clone(); + let current_rgba = Rc::clone(¤t_rgba); + let drawing_area = drawing_area.clone(); + let parent_window = btn.root().and_downcast::(); + let initial_color = current_rgba.borrow().clone(); + + dialog.choose_rgba(parent_window.as_ref(), Some(&initial_color), gtk::gio::Cancellable::NONE, move |res| { + if let Ok(new_rgba) = res { + let new_hex = format!( + "#{:02x}{:02x}{:02x}", + (new_rgba.red() * 255.0).round() as u8, + (new_rgba.green() * 255.0).round() as u8, + (new_rgba.blue() * 255.0).round() as u8, + ); + let changed = { + let mut comp = composite.borrow_mut(); + let res; + if is_emblem { + res = comp.emblem.as_mut().unwrap().update_color(&tag, &new_hex).unwrap_or(false); + } else { + res = comp.bg.update_color(&tag, &new_hex).unwrap_or(false); + } + if res { + comp.is_modified = true; + } + res + }; + if changed { + *current_rgba.borrow_mut() = new_rgba; + drawing_area.queue_draw(); + refresh_preview(); + } } - if res { - comp.is_modified = true; - } - res - }; - if changed { - refresh_preview(); - } + }); }); }