fix: replace GTK4 ColorDialogButton popovers with custom GTK buttons that spawn full native ColorDialog windows to avoid unresizing popovers

This commit is contained in:
2026-08-03 23:26:51 -04:00
parent 1e4154ab90
commit 3a2443c859
+60 -27
View File
@@ -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(&current_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(&current_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(&current_rgba);
let drawing_area = drawing_area.clone();
let parent_window = btn.root().and_downcast::<gtk::Window>();
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();
}
});
});
}