Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The long road to GTK4 #112

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,430 changes: 718 additions & 712 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
5 changes: 3 additions & 2 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@
rust
rust-analyzer-unwrapped
gcc
gtk3
gtk-layer-shell
gtk4
gtk4-layer-shell
pkg-config
openssl
gdk-pixbuf
Expand All @@ -127,6 +127,7 @@
hicolor-icon-theme
gsettings-desktop-schemas
libxkbcommon
graphene
];

RUST_SRC_PATH = "${rust}/lib/rustlib/src/rust/library";
Expand Down
19 changes: 9 additions & 10 deletions src/bar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -49,7 +49,6 @@ impl Bar {
) -> Self {
let window = ApplicationWindow::builder()
.application(app)
.type_(WindowType::Toplevel)
.build();

let name = config
Expand Down Expand Up @@ -81,16 +80,16 @@ 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();
Propagation::Proceed
// gtk::main_quit();
Propagation::Proceed
});

Self {
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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);
}};
}

Expand All @@ -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")]
Expand Down
24 changes: 12 additions & 12 deletions src/config/common.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -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(),
Expand All @@ -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);
Expand Down Expand Up @@ -119,29 +119,29 @@ 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);
});
}

revealer.connect_child_revealed_notify(move |revealer| {
if !revealer.reveals_child() {
container.hide();
widget.hide();
}
});
},
Expand Down
8 changes: 4 additions & 4 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down Expand Up @@ -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")]
Expand Down
1 change: 0 additions & 1 deletion src/config/truncate.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use gtk::pango::EllipsizeMode as GtkEllipsizeMode;
use gtk::prelude::*;
use serde::Deserialize;

#[derive(Debug, Deserialize, Clone, Copy)]
Expand Down
49 changes: 45 additions & 4 deletions src/gtk_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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 {
Expand All @@ -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 {
Expand All @@ -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
Expand All @@ -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)
// }
// }
// }
4 changes: 2 additions & 2 deletions src/image/gtk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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
Expand Down
39 changes: 22 additions & 17 deletions src/image/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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> {
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
Loading
Loading