start porting to gtk4

This commit is contained in:
Jake Stanger 2023-04-22 00:29:50 +01:00
parent 6595674af2
commit 29fd4cd926
No known key found for this signature in database
GPG Key ID: C51FC8F9CB0BEA61
27 changed files with 889 additions and 879 deletions

1462
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -69,8 +69,8 @@ workspaces = ["futures-util"]
[dependencies]
# core
gtk = "0.18.1"
gtk-layer-shell = "0.8.0"
gtk = { package = "gtk4", version = "0.7.3" }
gtk-layer-shell = { package = "gtk4-layer-shell", version = "0.2.0" }
glib = "0.18.5"
tokio = { version = "1.36.0", features = [
"macros",

View File

@ -115,8 +115,8 @@
rust
rust-analyzer-unwrapped
gcc
gtk3
gtk-layer-shell
gtk4
gtk4-layer-shell
pkg-config
openssl
gdk-pixbuf
@ -127,6 +127,7 @@
hicolor-icon-theme
gsettings-desktop-schemas
libxkbcommon
graphene
];
RUST_SRC_PATH = "${rust}/lib/rustlib/src/rust/library";

View File

@ -8,7 +8,7 @@ use color_eyre::Result;
use glib::Propagation;
use gtk::gdk::Monitor;
use gtk::prelude::*;
use gtk::{Application, ApplicationWindow, IconTheme, Orientation, Window, WindowType};
use gtk::{Application, ApplicationWindow, IconTheme, Orientation, Window};
use gtk_layer_shell::LayerShell;
use std::cell::RefCell;
use std::rc::Rc;
@ -49,7 +49,6 @@ impl Bar {
) -> Self {
let window = ApplicationWindow::builder()
.application(app)
.type_(WindowType::Toplevel)
.build();
let name = config
@ -81,15 +80,15 @@ impl Bar {
let center = create_container("center", orientation);
let end = create_container("end", orientation);
content.add(&start);
content.append(&start);
content.set_center_widget(Some(&center));
content.pack_end(&end, false, false, 0);
window.add(&content);
window.append(&content);
window.connect_destroy_event(|_, _| {
info!("Shutting down");
gtk::main_quit();
// gtk::main_quit();
Propagation::Proceed
});
@ -136,7 +135,7 @@ impl Bar {
.unwrap_or_else(|| config.autohide.is_some());
if let Some(autohide) = config.autohide {
let hotspot_window = Window::new(WindowType::Toplevel);
let hotspot_window = Window::new();
Self::setup_autohide(&self.window, &hotspot_window, autohide);
self.setup_layer_shell(
@ -367,7 +366,7 @@ fn add_modules(
set_widget_identifiers(&widget_parts, &common);
let container = wrap_widget(&widget_parts.widget, common, orientation);
content.add(&container);
content.append(&container);
}};
}
@ -389,8 +388,8 @@ fn add_modules(
ModuleConfig::Script(mut module) => add_module!(module, id),
#[cfg(feature = "sys_info")]
ModuleConfig::SysInfo(mut module) => add_module!(module, id),
#[cfg(feature = "tray")]
ModuleConfig::Tray(mut module) => add_module!(module, id),
// #[cfg(feature = "tray")]
// ModuleConfig::Tray(mut module) => add_module!(module, id),
#[cfg(feature = "upower")]
ModuleConfig::Upower(mut module) => add_module!(module, id),
#[cfg(feature = "workspaces")]

View File

@ -1,9 +1,9 @@
use crate::dynamic_value::{dynamic_string, DynamicBool};
use crate::script::{Script, ScriptInput};
use glib::Propagation;
use gtk::gdk::ScrollDirection;
use gtk::prelude::*;
use gtk::{EventBox, Orientation, Revealer, RevealerTransitionType};
use gtk::{GestureClick, Orientation, Revealer, RevealerTransitionType, Widget};
use gtk::gdk::ScrollDirection;
use serde::Deserialize;
use tracing::trace;
@ -56,14 +56,16 @@ impl TransitionType {
impl CommonConfig {
/// Configures the module's container according to the common config options.
pub fn install_events(mut self, container: &EventBox, revealer: &Revealer) {
pub fn install_events(mut self, container: &gtk::Box, revealer: &Revealer) {
self.install_show_if(container, revealer);
let left_click_script = self.on_click_left.map(Script::new_polling);
let middle_click_script = self.on_click_middle.map(Script::new_polling);
let right_click_script = self.on_click_right.map(Script::new_polling);
container.connect_button_press_event(move |_, event| {
let gesture = GestureClick::new();
gesture.connect_pressed(move |_, event| {
let script = match event.button() {
1 => left_click_script.as_ref(),
2 => middle_click_script.as_ref(),
@ -75,8 +77,6 @@ impl CommonConfig {
trace!("Running on-click script: {}", event.button());
script.run_as_oneshot(None);
}
Propagation::Proceed
});
let scroll_up_script = self.on_scroll_up.map(Script::new_polling);
@ -119,21 +119,21 @@ impl CommonConfig {
}
}
fn install_show_if(&mut self, container: &EventBox, revealer: &Revealer) {
fn install_show_if<W: IsA<Widget>>(&mut self, widget: &W, revealer: &Revealer) {
self.show_if.take().map_or_else(
|| {
container.show_all();
widget.set_visible(true)
},
|show_if| {
let container = container.clone();
let widget = widget.clone();
{
let revealer = revealer.clone();
let container = container.clone();
let widget = widget.clone();
show_if.subscribe(move |success| {
if success {
container.show_all();
widget.show_all();
}
revealer.set_reveal_child(success);
});
@ -141,7 +141,7 @@ impl CommonConfig {
revealer.connect_child_revealed_notify(move |revealer| {
if !revealer.reveals_child() {
container.hide();
widget.hide();
}
});
},

View File

@ -17,8 +17,8 @@ use crate::modules::music::MusicModule;
use crate::modules::script::ScriptModule;
#[cfg(feature = "sys_info")]
use crate::modules::sysinfo::SysInfoModule;
#[cfg(feature = "tray")]
use crate::modules::tray::TrayModule;
// #[cfg(feature = "tray")]
// use crate::modules::tray::TrayModule;
#[cfg(feature = "upower")]
use crate::modules::upower::UpowerModule;
#[cfg(feature = "workspaces")]
@ -48,8 +48,8 @@ pub enum ModuleConfig {
Script(Box<ScriptModule>),
#[cfg(feature = "sys_info")]
SysInfo(Box<SysInfoModule>),
#[cfg(feature = "tray")]
Tray(Box<TrayModule>),
// #[cfg(feature = "tray")]
// Tray(Box<TrayModule>),
#[cfg(feature = "upower")]
Upower(Box<UpowerModule>),
#[cfg(feature = "workspaces")]

View File

@ -1,5 +1,4 @@
use gtk::pango::EllipsizeMode as GtkEllipsizeMode;
use gtk::prelude::*;
use serde::Deserialize;
#[derive(Debug, Deserialize, Clone, Copy)]

View File

@ -8,7 +8,7 @@ use gtk::{Orientation, Widget};
pub struct WidgetGeometry {
/// Position of the start edge of the widget
/// from the start edge of the bar.
pub position: i32,
pub position: f64,
/// The length of the widget.
pub size: i32,
/// The length of the bar.
@ -25,6 +25,8 @@ pub trait IronbarGtkExt {
fn get_tag<V: 'static>(&self, key: &str) -> Option<&V>;
/// Sets a data tag on a widget.
fn set_tag<V: 'static>(&self, key: &str, value: V);
fn children(&self) -> Vec<Box<dyn AsRef<Widget>>>;
}
impl<W: IsA<Widget>> IronbarGtkExt for W {
@ -41,7 +43,7 @@ impl<W: IsA<Widget>> IronbarGtkExt for W {
allocation.height()
};
let top_level = self.toplevel().expect("Failed to get top-level widget");
let top_level = self.root().expect("Failed to get root widget");
let top_level_allocation = top_level.allocation();
let bar_size = if orientation == Orientation::Horizontal {
@ -51,8 +53,8 @@ impl<W: IsA<Widget>> IronbarGtkExt for W {
};
let (widget_x, widget_y) = self
.translate_coordinates(&top_level, 0, 0)
.unwrap_or((0, 0));
.translate_coordinates(&top_level, 0.0, 0.0)
.unwrap_or((0.0, 0.0));
let widget_pos = if orientation == Orientation::Horizontal {
widget_x
@ -74,4 +76,43 @@ impl<W: IsA<Widget>> IronbarGtkExt for W {
fn set_tag<V: 'static>(&self, key: &str, value: V) {
unsafe { self.set_data(key, value) }
}
fn children(&self) -> Vec<Box<dyn AsRef<Widget>>> {
let mut widget = self.first_child();
let mut children = vec![];
while let Some(w) = widget {
children.push(Box::new(w));
widget = w.next_sibling();
}
children
}
}
// struct IteratorWrapper<W: IsA<Widget>>(W);
//
// impl<W> Iterator for IteratorWrapper<W> {
// type Item = Box<dyn AsRef<Widget>>;
//
// fn next(&mut self) -> Option<Self::Item> {
// self.0
// }
// }
//
// struct IntoIter<W: IsA<Widget>> {
// widget: W,
// next: Option<Box<dyn AsRef<Widget>>>
// }
//
// impl<W: IsA<Widget>> IntoIterator for IteratorWrapper<W> {
// type Item = Box<dyn AsRef<Widget>>;
// type IntoIter = IntoIter<Self>;
//
// fn into_iter(self) -> Self::IntoIter {
// IntoIter {
// widget: self,
// next: self.first_child().map(Box::new)
// }
// }
// }

View File

@ -39,7 +39,7 @@ pub fn new_icon_label(input: &str, icon_theme: &IconTheme, size: i32) -> gtk::Bo
image.add_class("icon");
image.add_class("image");
container.add(&image);
container.append(&image);
ImageProvider::parse(input, icon_theme, false, size)
.map(|provider| provider.load_into_image(image));
@ -48,7 +48,7 @@ pub fn new_icon_label(input: &str, icon_theme: &IconTheme, size: i32) -> gtk::Bo
label.add_class("icon");
label.add_class("text-icon");
container.add(&label);
container.append(&label);
}
container

View File

@ -4,11 +4,12 @@ use crate::{glib_recv_mpsc, send_async, spawn};
use cfg_if::cfg_if;
use color_eyre::{Help, Report, Result};
use gtk::cairo::Surface;
use gtk::gdk::ffi::gdk_cairo_surface_create_from_pixbuf;
use gtk::gdk_pixbuf::Pixbuf;
use gtk::prelude::*;
use gtk::{IconLookupFlags, IconTheme};
use std::path::{Path, PathBuf};
use gtk::gdk::ffi::gdk_texture_new_for_pixbuf;
use gtk::gdk::Texture;
#[cfg(feature = "http")]
use tokio::sync::mpsc;
use tracing::warn;
@ -205,22 +206,26 @@ impl<'a> ImageProvider<'a> {
Self::create_and_load_surface(&pixbuf, image, scale)
}
/// Attempts to create a Cairo surface from the provided `Pixbuf`,
/// using the provided scaling factor.
/// The surface is then loaded into the provided image.
///
/// This is necessary for HiDPI since `Pixbuf`s are always treated as scale factor 1.
fn create_and_load_surface(pixbuf: &Pixbuf, image: &gtk::Image, scale: i32) -> Result<()> {
let surface = unsafe {
let ptr =
gdk_cairo_surface_create_from_pixbuf(pixbuf.as_ptr(), scale, std::ptr::null_mut());
Surface::from_raw_full(ptr)
}?;
image.set_from_surface(Some(&surface));
Ok(())
}
// /// Attempts to create a Cairo surface from the provided `Pixbuf`,
// /// using the provided scaling factor.
// /// The surface is then loaded into the provided image.
// ///
// /// This is necessary for HiDPI since `Pixbuf`s are always treated as scale factor 1.
// fn create_and_load_surface(pixbuf: &Pixbuf, image: &gtk::Image, scale: i32) -> Result<()> {
// pixbuf.pai
// let surface = unsafe {
// let ptr = gdk_texture_new_for_pixbuf(pixbuf.as_ptr());
// gdk_cairo_surface_create_from_pixbuf(pixbuf.as_ptr(), scale, std::ptr::null_mut());
// Surface::from_raw_full(ptr)
// Texture::from_
// }?;
//
// image.set_from_paintable()
//
// image.set_from_surface(Some(&surface));
//
// Ok(())
// }
/// Attempts to get a `Pixbuf` from the GTK icon theme.
fn get_from_icon(&self, name: &str, theme: &IconTheme, scale: i32) -> Result<Pixbuf> {

View File

@ -301,7 +301,7 @@ fn load_config() -> Config {
}
/// Gets the GDK `Display` instance.
fn get_display() -> Display {
pub fn get_display() -> Display {
Display::default().map_or_else(
|| {
let report = Report::msg("Failed to get default GTK display");

View File

@ -10,7 +10,7 @@ use glib::Propagation;
use gtk::gdk_pixbuf::Pixbuf;
use gtk::gio::{Cancellable, MemoryInputStream};
use gtk::prelude::*;
use gtk::{Button, EventBox, Image, Label, Orientation, RadioButton, Widget};
use gtk::{Button, Image, Label, Orientation, CheckButton, Widget};
use serde::Deserialize;
use std::collections::HashMap;
use std::sync::Arc;
@ -155,10 +155,10 @@ impl Module<Button> for ClipboardModule {
let container = gtk::Box::new(Orientation::Vertical, 10);
let entries = gtk::Box::new(Orientation::Vertical, 5);
container.add(&entries);
container.append(&entries);
let hidden_option = RadioButton::new();
entries.add(&hidden_option);
let hidden_option = CheckButton::new();
entries.append(&hidden_option);
let mut items = HashMap::new();
@ -174,10 +174,10 @@ impl Module<Button> for ClipboardModule {
let button = match item.value.as_ref() {
ClipboardValue::Text(value) => {
let button = RadioButton::from_widget(&hidden_option);
let button = CheckButton::from_widget(&hidden_option);
let label = Label::new(Some(value));
button.add(&label);
button.append(&label);
if let Some(truncate) = self.truncate {
truncate.truncate_label(&label);
@ -198,7 +198,7 @@ impl Module<Button> for ClipboardModule {
.expect("Failed to read Pixbuf from stream");
let image = Image::from_pixbuf(Some(&pixbuf));
let button = RadioButton::from_widget(&hidden_option);
let button = CheckButton::from_widget(&hidden_option);
button.set_image(Some(&image));
button.set_always_show_image(true);
button.style_context().add_class("image");
@ -211,15 +211,12 @@ impl Module<Button> for ClipboardModule {
button.style_context().add_class("btn");
button.set_active(true); // if just added, should be on clipboard
let button_wrapper = EventBox::new();
button_wrapper.add(&button);
button_wrapper.set_widget_name(&format!("copy-{id}"));
button_wrapper.set_above_child(true);
button.set_widget_name(&format!("copy-{id}"));
button.set_above_child(true);
{
let tx = tx.clone();
button_wrapper.connect_button_press_event(
button.connect_button_press_event(
move |button_wrapper, event| {
// left click
if event.button() == 1 {
@ -255,12 +252,11 @@ impl Module<Button> for ClipboardModule {
});
}
row.add(&button_wrapper);
row.pack_end(&remove_button, false, false, 0);
row.append(&button);
row.pack_end(&remove_button, false);
entries.add(&row);
entries.append(&row);
entries.reorder_child(&row, 0);
row.show_all();
items.insert(id, (row, button));
}
@ -292,7 +288,6 @@ impl Module<Button> for ClipboardModule {
});
}
container.show_all();
hidden_option.hide();
Some(container)

View File

@ -100,7 +100,6 @@ impl Module<Button> for ClockModule {
) -> Result<ModuleParts<Button>> {
let button = Button::new();
let label = Label::builder()
.angle(info.bar_position.get_angle())
.use_markup(true)
.build();
button.add(&label);
@ -140,11 +139,11 @@ impl Module<Button> for ClockModule {
.build();
clock.add_class("calendar-clock");
container.add(&clock);
container.append(&clock);
let calendar = Calendar::new();
calendar.add_class("calendar");
container.add(&calendar);
container.append(&calendar);
let format = self.format_popup;
let locale = Locale::try_from(self.locale.as_str()).unwrap_or(Locale::POSIX);
@ -154,8 +153,6 @@ impl Module<Button> for ClockModule {
clock.set_label(&date_string);
});
container.show_all();
Some(container)
}
}

View File

@ -248,8 +248,6 @@ impl Module<gtk::Box> for CustomModule {
}
}
container.show_all();
Some(container)
}
}

View File

@ -1,6 +1,5 @@
use glib::Propagation;
use std::cell::Cell;
use std::ops::Neg;
use gtk::prelude::*;
use gtk::Scale;

View File

@ -3,7 +3,6 @@ use crate::dynamic_value::dynamic_string;
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
use crate::{glib_recv, try_send};
use color_eyre::Result;
use gtk::prelude::*;
use gtk::Label;
use serde::Deserialize;
use tokio::sync::mpsc;

View File

@ -262,8 +262,6 @@ impl ItemButton {
});
}
button.show_all();
Self {
button,
persistent: item.favorite,

View File

@ -340,7 +340,7 @@ impl Module<gtk::Box> for LauncherModule {
&controller_tx,
);
container.add(&button.button);
container.append(&button.button);
buttons.insert(item.app_id, button);
}
}
@ -423,7 +423,7 @@ impl Module<gtk::Box> for LauncherModule {
// we need some content to force the container to have a size
let placeholder = Button::with_label("PLACEHOLDER");
placeholder.set_width_request(MAX_WIDTH);
container.add(&placeholder);
container.append(&placeholder);
let mut buttons = IndexMap::<String, IndexMap<usize, Button>>::new();
@ -507,10 +507,9 @@ impl Module<gtk::Box> for LauncherModule {
if let Some(buttons) = buttons.get(&app_id) {
for (_, button) in buttons {
button.style_context().add_class("popup-item");
container.add(button);
container.append(button);
}
container.show_all();
container.set_width_request(MAX_WIDTH);
}
}

View File

@ -5,9 +5,9 @@ use std::sync::Arc;
use color_eyre::Result;
use glib::IsA;
use gtk::gdk::{EventMask, Monitor};
use gtk::gdk::Monitor;
use gtk::prelude::*;
use gtk::{Application, Button, EventBox, IconTheme, Orientation, Revealer, Widget};
use gtk::{Application, Button, IconTheme, Orientation, Revealer, Widget};
use tokio::sync::{broadcast, mpsc};
use tracing::debug;
@ -38,8 +38,8 @@ pub mod music;
pub mod script;
#[cfg(feature = "sys_info")]
pub mod sysinfo;
#[cfg(feature = "tray")]
pub mod tray;
// #[cfg(feature = "tray")]
// pub mod tray;
#[cfg(feature = "upower")]
pub mod upower;
#[cfg(feature = "workspaces")]
@ -379,7 +379,7 @@ pub fn wrap_widget<W: IsA<Widget>>(
widget: &W,
common: CommonConfig,
orientation: Orientation,
) -> EventBox {
) -> gtk::Box {
let transition_type = common
.transition_type
.as_ref()
@ -394,11 +394,11 @@ pub fn wrap_widget<W: IsA<Widget>>(
revealer.add(widget);
revealer.set_reveal_child(true);
let container = EventBox::new();
let container = gtk::Box::new(Orientation::Horizontal, 0);
container.add_class("widget-container");
container.add_events(EventMask::SCROLL_MASK);
container.add(&revealer);
// container.add_events(EventMask::SCROLL_MASK);
container.append(&revealer);
common.install_events(&container, &revealer);

View File

@ -187,21 +187,19 @@ impl Module<Button> for MusicModule {
let button_contents = gtk::Box::new(Orientation::Horizontal, 5);
button_contents.add_class("contents");
button.add(&button_contents);
button.append(&button_contents);
let icon_play = new_icon_label(&self.icons.play, info.icon_theme, self.icon_size);
let icon_pause = new_icon_label(&self.icons.pause, info.icon_theme, self.icon_size);
let label = Label::new(None);
label.set_angle(info.bar_position.get_angle());
if let Some(truncate) = self.truncate {
truncate.truncate_label(&label);
}
button_contents.add(&icon_pause);
button_contents.add(&icon_play);
button_contents.add(&label);
button_contents.append(&icon_pause);
button_contents.append(&icon_play);
button_contents.append(&label);
{
let tx = context.tx.clone();
@ -289,9 +287,9 @@ impl Module<Button> for MusicModule {
album_label.container.add_class("album");
artist_label.container.add_class("artist");
info_box.add(&title_label.container);
info_box.add(&album_label.container);
info_box.add(&artist_label.container);
info_box.append(&title_label.container);
info_box.append(&album_label.container);
info_box.append(&artist_label.container);
let controls_box = gtk::Box::new(Orientation::Horizontal, 0);
controls_box.add_class("controls");
@ -308,12 +306,12 @@ impl Module<Button> for MusicModule {
let btn_next = new_icon_button(&icons.next, icon_theme, self.icon_size);
btn_next.add_class("btn-next");
controls_box.add(&btn_prev);
controls_box.add(&btn_play);
controls_box.add(&btn_pause);
controls_box.add(&btn_next);
controls_box.append(&btn_prev);
controls_box.append(&btn_play);
controls_box.append(&btn_pause);
controls_box.append(&btn_next);
info_box.add(&controls_box);
info_box.append(&controls_box);
let volume_box = gtk::Box::new(Orientation::Vertical, 5);
volume_box.add_class("volume");
@ -328,9 +326,9 @@ impl Module<Button> for MusicModule {
volume_box.pack_start(&volume_slider, true, true, 0);
volume_box.pack_end(&volume_icon, false, false, 0);
main_container.add(&album_image);
main_container.add(&info_box);
main_container.add(&volume_box);
main_container.append(&album_image);
main_container.append(&info_box);
main_container.append(&volume_box);
container.add(&main_container);
let tx_prev = tx.clone();
@ -396,8 +394,6 @@ impl Module<Button> for MusicModule {
});
}
container.show_all();
{
let icon_theme = icon_theme.clone();
let image_size = self.cover_image_size;
@ -550,8 +546,8 @@ impl IconLabel {
icon.add_class("icon-box");
label.add_class("label");
container.add(&icon);
container.add(&label);
container.append(&icon);
container.append(&label);
Self { label, container }
}

View File

@ -3,7 +3,6 @@ use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetC
use crate::script::{OutputStream, Script, ScriptMode};
use crate::{glib_recv, spawn, try_send};
use color_eyre::{Help, Report, Result};
use gtk::prelude::*;
use gtk::Label;
use serde::Deserialize;
use tokio::sync::mpsc;
@ -85,7 +84,6 @@ impl Module<Label> for ScriptModule {
info: &ModuleInfo,
) -> Result<ModuleParts<Label>> {
let label = Label::builder().use_markup(true).build();
label.set_angle(info.bar_position.get_angle());
{
let label = label.clone();

View File

@ -196,9 +196,8 @@ impl Module<gtk::Box> for SysInfoModule {
let label = Label::builder().label(format).use_markup(true).build();
label.add_class("item");
label.set_angle(info.bar_position.get_angle());
container.add(&label);
container.append(&label);
labels.push(label);
}

View File

@ -2,7 +2,6 @@ use glib::ffi::g_strfreev;
use glib::translate::ToGlibPtr;
use gtk::ffi::gtk_icon_theme_get_search_path;
use gtk::gdk_pixbuf::{Colorspace, InterpType};
use gtk::prelude::IconThemeExt;
use gtk::{gdk_pixbuf, IconLookupFlags, IconTheme, Image};
use std::collections::HashSet;
use std::ffi::CStr;

View File

@ -180,7 +180,6 @@ impl Module<gtk::Button> for UpowerModule {
try_send!(tx, ModuleUpdateEvent::TogglePopup(button.popup_id()));
});
label.set_angle(info.bar_position.get_angle());
let format = self.format.clone();
let rx = context.subscribe();

View File

@ -11,6 +11,7 @@ use std::cmp::Ordering;
use std::collections::{HashMap, HashSet};
use tokio::sync::mpsc::{Receiver, Sender};
use tracing::{debug, trace, warn};
use crate::gtk_helpers::IronbarGtkExt;
#[derive(Debug, Deserialize, Clone, Copy, Eq, PartialEq)]
#[serde(rename_all = "snake_case")]
@ -225,7 +226,7 @@ impl Module<gtk::Box> for WorkspacesModule {
&context.controller_tx,
);
container.add(&item);
container.append(&item);
button_map.insert(name.to_string(), item);
};
@ -261,7 +262,6 @@ impl Module<gtk::Box> for WorkspacesModule {
reorder_workspaces(&container);
}
container.show_all();
has_initialized = true;
}
}
@ -299,7 +299,7 @@ impl Module<gtk::Box> for WorkspacesModule {
&context.controller_tx,
);
container.add(&item);
container.append(&item);
if self.sort == SortOrder::Alphanumeric {
reorder_workspaces(&container);
}
@ -324,7 +324,7 @@ impl Module<gtk::Box> for WorkspacesModule {
&context.controller_tx,
);
container.add(&item);
container.append(&item);
if self.sort == SortOrder::Alphanumeric {
reorder_workspaces(&container);

View File

@ -151,7 +151,7 @@ impl Popup {
if let Some(PopupCacheValue { content, .. }) = self.cache.get(&widget_id) {
content.container.style_context().add_class("popup");
self.window.add(&content.container);
self.window.append(&content.container);
self.window.show();
self.set_pos(geometry);

View File

@ -1,8 +1,6 @@
use crate::{glib_recv_mpsc, spawn, try_send};
use color_eyre::{Help, Report};
use crate::{get_display, glib_recv_mpsc, spawn, try_send};
use gtk::ffi::GTK_STYLE_PROVIDER_PRIORITY_USER;
use gtk::prelude::CssProviderExt;
use gtk::{gdk, gio, CssProvider, StyleContext};
use gtk::{gio, CssProvider};
use notify::event::ModifyKind;
use notify::{recommended_watcher, Event, EventKind, RecursiveMode, Result, Watcher};
use std::env;
@ -26,19 +24,10 @@ pub fn load_css(style_path: PathBuf) {
};
let provider = CssProvider::new();
provider.load_from_file(&gio::File::for_path(&style_path));
match provider.load_from_file(&gio::File::for_path(&style_path)) {
Ok(()) => debug!("Loaded css from '{}'", style_path.display()),
Err(err) => error!("{:?}", Report::new(err)
.wrap_err("Failed to load CSS")
.suggestion("Check the CSS file for errors")
.suggestion("GTK CSS uses a subset of the full CSS spec and many properties are not available. Ensure you are not using any unsupported property.")
)
};
let screen = gdk::Screen::default().expect("Failed to get default GTK screen");
StyleContext::add_provider_for_screen(
&screen,
gtk::style_context_add_provider_for_display(
&get_display(),
&provider,
GTK_STYLE_PROVIDER_PRIORITY_USER as u32,
);
@ -74,12 +63,6 @@ pub fn load_css(style_path: PathBuf) {
glib_recv_mpsc!(rx, path => {
info!("Reloading CSS");
if let Err(err) = provider.load_from_file(&gio::File::for_path(path)) {
error!("{:?}", Report::new(err)
.wrap_err("Failed to load CSS")
.suggestion("Check the CSS file for errors")
.suggestion("GTK CSS uses a subset of the full CSS spec and many properties are not available. Ensure you are not using any unsupported property.")
);
}
provider.load_from_file(&gio::File::for_path(path));
});
}