1
0
Fork 0
mirror of https://github.com/Zedfrigg/ironbar.git synced 2025-07-01 10:41:03 +02:00

fix: popup placement issues

This commit is contained in:
Jake Stanger 2022-08-15 21:11:00 +01:00
parent 8518262053
commit 8576ac5c44
No known key found for this signature in database
GPG key ID: C51FC8F9CB0BEA61
7 changed files with 54 additions and 66 deletions

View file

@ -31,7 +31,7 @@ pub fn create_bar(app: &Application, monitor: &Monitor, monitor_name: &str, conf
content.set_center_widget(Some(&center)); content.set_center_widget(Some(&center));
content.pack_end(&right, false, false, 0); content.pack_end(&right, false, false, 0);
load_modules(&left, &center, &right, app, config, monitor_name); load_modules(&left, &center, &right, app, config, monitor, monitor_name);
win.add(&content); win.add(&content);
win.connect_destroy_event(|_, _| { win.connect_destroy_event(|_, _| {
@ -48,6 +48,7 @@ fn load_modules(
right: &gtk::Box, right: &gtk::Box,
app: &Application, app: &Application,
config: Config, config: Config,
monitor: &Monitor,
output_name: &str, output_name: &str,
) { ) {
if let Some(modules) = config.left { if let Some(modules) = config.left {
@ -55,10 +56,11 @@ fn load_modules(
app, app,
location: ModuleLocation::Left, location: ModuleLocation::Left,
bar_position: &config.position, bar_position: &config.position,
monitor,
output_name, output_name,
}; };
add_modules(left, modules, info); add_modules(left, modules, &info);
} }
if let Some(modules) = config.center { if let Some(modules) = config.center {
@ -66,10 +68,11 @@ fn load_modules(
app, app,
location: ModuleLocation::Center, location: ModuleLocation::Center,
bar_position: &config.position, bar_position: &config.position,
monitor,
output_name, output_name,
}; };
add_modules(center, modules, info); add_modules(center, modules, &info);
} }
if let Some(modules) = config.right { if let Some(modules) = config.right {
@ -77,14 +80,15 @@ fn load_modules(
app, app,
location: ModuleLocation::Right, location: ModuleLocation::Right,
bar_position: &config.position, bar_position: &config.position,
monitor,
output_name, output_name,
}; };
add_modules(right, modules, info); add_modules(right, modules, &info);
} }
} }
fn add_modules(content: &gtk::Box, modules: Vec<ModuleConfig>, info: ModuleInfo) { fn add_modules(content: &gtk::Box, modules: Vec<ModuleConfig>, info: &ModuleInfo) {
macro_rules! add_module { macro_rules! add_module {
($module:expr, $name:literal) => {{ ($module:expr, $name:literal) => {{
let widget = $module.into_widget(&info); let widget = $module.into_widget(&info);

View file

@ -2,7 +2,6 @@ mod popup;
use self::popup::Popup; use self::popup::Popup;
use crate::modules::{Module, ModuleInfo}; use crate::modules::{Module, ModuleInfo};
use crate::popup::PopupAlignment;
use chrono::Local; use chrono::Local;
use glib::Continue; use glib::Continue;
use gtk::prelude::*; use gtk::prelude::*;
@ -33,6 +32,7 @@ impl Module<Button> for ClockModule {
let popup = Popup::new( let popup = Popup::new(
"popup-clock", "popup-clock",
info.app, info.app,
info.monitor,
Orientation::Vertical, Orientation::Vertical,
info.bar_position, info.bar_position,
); );
@ -41,14 +41,7 @@ impl Module<Button> for ClockModule {
button.show_all(); button.show_all();
button.connect_clicked(move |button| { button.connect_clicked(move |button| {
let button_w = button.allocation().width(); popup.show(button);
let (button_x, _) = button
.translate_coordinates(&button.toplevel().unwrap(), 0, 0)
.unwrap();
popup.show();
popup.set_pos(f64::from(button_x + button_w), PopupAlignment::Right);
}); });
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT); let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);

View file

@ -2,7 +2,6 @@ use crate::collection::Collection;
use crate::icon::{find_desktop_file, get_icon}; use crate::icon::{find_desktop_file, get_icon};
use crate::modules::launcher::popup::Popup; use crate::modules::launcher::popup::Popup;
use crate::modules::launcher::FocusEvent; use crate::modules::launcher::FocusEvent;
use crate::popup::PopupAlignment;
use crate::sway::SwayNode; use crate::sway::SwayNode;
use gtk::prelude::*; use gtk::prelude::*;
use gtk::{Button, IconTheme, Image}; use gtk::{Button, IconTheme, Image};
@ -175,19 +174,8 @@ impl LauncherItem {
button.connect_enter_notify_event(move |button, _| { button.connect_enter_notify_event(move |button, _| {
let windows = windows.lock().unwrap(); let windows = windows.lock().unwrap();
if windows.len() > 1 { if windows.len() > 1 {
let button_w = button.allocation().width();
let (button_x, _) = button
.translate_coordinates(&button.toplevel().unwrap(), 0, 0)
.unwrap();
let button_center = f64::from(button_x) + f64::from(button_w) / 2.0;
popup.set_windows(windows.as_slice(), &tx_hover); popup.set_windows(windows.as_slice(), &tx_hover);
popup.show(); popup.show(button);
// TODO: Pass through module location
popup.set_pos(button_center, PopupAlignment::Center);
} }
Inhibit(false) Inhibit(false)

View file

@ -194,6 +194,7 @@ impl Module<gtk::Box> for LauncherModule {
let popup = Popup::new( let popup = Popup::new(
"popup-launcher", "popup-launcher",
info.app, info.app,
info.monitor,
Orientation::Vertical, Orientation::Vertical,
info.bar_position, info.bar_position,
); );

View file

@ -17,6 +17,7 @@ use crate::config::BarPosition;
/// Shamelessly stolen from here: /// Shamelessly stolen from here:
/// <https://github.com/zeroeightysix/rustbar/blob/master/src/modules/module.rs> /// <https://github.com/zeroeightysix/rustbar/blob/master/src/modules/module.rs>
use glib::IsA; use glib::IsA;
use gtk::gdk::Monitor;
use gtk::{Application, Widget}; use gtk::{Application, Widget};
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde_json::Value; use serde_json::Value;
@ -32,6 +33,7 @@ pub struct ModuleInfo<'a> {
pub app: &'a Application, pub app: &'a Application,
pub location: ModuleLocation, pub location: ModuleLocation,
pub bar_position: &'a BarPosition, pub bar_position: &'a BarPosition,
pub monitor: &'a Monitor,
pub output_name: &'a str, pub output_name: &'a str,
} }

View file

@ -5,7 +5,6 @@ use self::popup::Popup;
use crate::modules::mpd::client::{get_connection, get_duration, get_elapsed}; use crate::modules::mpd::client::{get_connection, get_duration, get_elapsed};
use crate::modules::mpd::popup::{MpdPopup, PopupEvent}; use crate::modules::mpd::popup::{MpdPopup, PopupEvent};
use crate::modules::{Module, ModuleInfo}; use crate::modules::{Module, ModuleInfo};
use crate::popup::PopupAlignment;
use dirs::home_dir; use dirs::home_dir;
use glib::Continue; use glib::Continue;
use gtk::prelude::*; use gtk::prelude::*;
@ -80,7 +79,7 @@ fn get_tokens(re: &Regex, format_string: &str) -> Vec<String> {
} }
enum Event { enum Event {
Open(f64), Open,
Update(Box<Option<(Song, Status, String)>>), Update(Box<Option<(Song, Status, String)>>),
} }
@ -96,6 +95,7 @@ impl Module<Button> for MpdModule {
let popup = Popup::new( let popup = Popup::new(
"popup-mpd", "popup-mpd",
info.app, info.app,
info.monitor,
Orientation::Horizontal, Orientation::Horizontal,
info.bar_position, info.bar_position,
); );
@ -106,16 +106,8 @@ impl Module<Button> for MpdModule {
let music_dir = self.music_dir.clone(); let music_dir = self.music_dir.clone();
button.connect_clicked(move |button| { button.connect_clicked(move |_| {
let button_w = button.allocation().width(); click_tx.send(Event::Open).unwrap();
let (button_x, _) = button
.translate_coordinates(&button.toplevel().unwrap(), 0, 0)
.unwrap();
click_tx
.send(Event::Open(f64::from(button_x + button_w)))
.unwrap();
}); });
let host = self.host.clone(); let host = self.host.clone();
@ -167,9 +159,8 @@ impl Module<Button> for MpdModule {
rx.attach(None, move |event| { rx.attach(None, move |event| {
match event { match event {
Event::Open(pos) => { Event::Open => {
mpd_popup.popup.show(); mpd_popup.popup.show(&button);
mpd_popup.popup.set_pos(pos, PopupAlignment::Right);
} }
Event::Update(mut msg) => { Event::Update(mut msg) => {
if let Some((song, status, string)) = msg.take() { if let Some((song, status, string)) = msg.take() {
@ -220,7 +211,7 @@ impl MpdModule {
PlayState::Playing => self.icon_play.as_ref(), PlayState::Playing => self.icon_play.as_ref(),
PlayState::Paused => self.icon_pause.as_ref(), PlayState::Paused => self.icon_pause.as_ref(),
}; };
icon.map(|i| i.as_str()) icon.map(String::as_str)
} }
"title" => song.title(), "title" => song.title(),
"album" => try_get_first_tag(song.tags.get(&Tag::Album)), "album" => try_get_first_tag(song.tags.get(&Tag::Album)),

View file

@ -1,23 +1,20 @@
use crate::config::BarPosition; use crate::config::BarPosition;
use gtk::gdk::Monitor;
use gtk::prelude::*; use gtk::prelude::*;
use gtk::{Application, ApplicationWindow, Orientation}; use gtk::{Application, ApplicationWindow, Button, Orientation};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Popup { pub struct Popup {
pub window: ApplicationWindow, pub window: ApplicationWindow,
pub container: gtk::Box, pub container: gtk::Box,
} monitor: Monitor,
pub enum PopupAlignment {
Left,
Center,
Right,
} }
impl Popup { impl Popup {
pub fn new( pub fn new(
name: &str, name: &str,
app: &Application, app: &Application,
monitor: &Monitor,
orientation: Orientation, orientation: Orientation,
bar_position: &BarPosition, bar_position: &BarPosition,
) -> Self { ) -> Self {
@ -72,11 +69,11 @@ impl Popup {
win.add(&content); win.add(&content);
win.connect_leave_notify_event(|win, ev| { win.connect_leave_notify_event(|win, ev| {
const THRESHOLD: f64 = 3.0;
let (w, _h) = win.size(); let (w, _h) = win.size();
let (x, y) = ev.position(); let (x, y) = ev.position();
const THRESHOLD: f64 = 3.0;
// some child widgets trigger this event // some child widgets trigger this event
// so check we're actually outside the window // so check we're actually outside the window
if x < THRESHOLD || y < THRESHOLD || x > f64::from(w) - THRESHOLD { if x < THRESHOLD || y < THRESHOLD || x > f64::from(w) - THRESHOLD {
@ -89,29 +86,41 @@ impl Popup {
Self { Self {
window: win, window: win,
container: content, container: content,
monitor: monitor.clone(),
} }
} }
/// Sets the popover's X position relative to the left border of the screen
pub fn set_pos(&self, pos: f64, alignment: PopupAlignment) {
let width = self.window.allocated_width();
let offset = match alignment {
PopupAlignment::Left => pos,
PopupAlignment::Center => (pos - (f64::from(width) / 2.0)).round(),
PopupAlignment::Right => pos - f64::from(width),
};
gtk_layer_shell::set_margin(&self.window, gtk_layer_shell::Edge::Left, offset as i32);
}
/// Shows the popover /// Shows the popover
pub fn show(&self) { pub fn show(&self, button: &Button) {
self.window.show_all(); self.window.show_all();
self.set_pos(button);
} }
/// Hides the popover /// Hides the popover
pub fn hide(&self) { pub fn hide(&self) {
self.window.hide(); self.window.hide();
} }
/// Sets the popover's X position relative to the left border of the screen
fn set_pos(&self, button: &Button) {
let widget_width = button.allocation().width();
let screen_width = self.monitor.workarea().width();
let popup_width = self.window.allocated_width();
let (widget_x, _) = button
.translate_coordinates(&button.toplevel().unwrap(), 0, 0)
.unwrap();
let widget_center = f64::from(widget_x) + f64::from(widget_width) / 2.0;
let mut offset = (widget_center - (f64::from(popup_width) / 2.0)).round();
if offset < 5.0 {
offset = 5.0;
} else if offset > f64::from(screen_width - popup_width) - 5.0 {
offset = f64::from(screen_width - popup_width) - 5.0;
}
gtk_layer_shell::set_margin(&self.window, gtk_layer_shell::Edge::Left, offset as i32);
}
} }