mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-04-19 11:24:24 +02:00
feat: mouse event config options
Adds `on_click_middle`, `on_click_right`, `on_scroll_up`, `on_scroll_down`. BREAKING CHANGE: `on_click` is now called `on_click_left` for consistency with new options. Resolves #44.
This commit is contained in:
parent
b2afe78c07
commit
fa67d077b1
5 changed files with 167 additions and 107 deletions
|
@ -1,10 +1,12 @@
|
|||
By default, you get a single bar at the bottom of all your screens.
|
||||
To change that, you'll unsurprisingly need a config file.
|
||||
|
||||
This page details putting together the skeleton for your config to get you to a stage where you can start configuring modules.
|
||||
It may look long and overwhelming, but that is just because the bar supports a lot of scenarios!
|
||||
This page details putting together the skeleton for your config to get you to a stage where you can start configuring
|
||||
modules.
|
||||
It may look long and overwhelming, but that is just because the bar supports a lot of scenarios!
|
||||
|
||||
If you want to see some ready-to-go config files check the [examples folder](https://github.com/JakeStanger/ironbar/tree/master/examples)
|
||||
If you want to see some ready-to-go config files check
|
||||
the [examples folder](https://github.com/JakeStanger/ironbar/tree/master/examples)
|
||||
and the example pages in the sidebar.
|
||||
|
||||
## 1. Create config file
|
||||
|
@ -239,7 +241,7 @@ monitors:
|
|||
<details>
|
||||
<summary>Corn</summary>
|
||||
|
||||
```
|
||||
```corn
|
||||
{
|
||||
monitors.DP-1 = [
|
||||
{ start = [] }
|
||||
|
@ -281,8 +283,12 @@ For details on available modules and each of their config options, check the sid
|
|||
|
||||
For information on the `Script` type, and embedding scripts in strings, see [here](script).
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|------------|--------------------|---------|--------------------------------------------------------------------------------------------------------------------|
|
||||
| `show_if` | `Script [polling]` | `null` | Polls the script to check its exit code. If exit code is zero, the module is shown. For other codes, it is hidden. |
|
||||
| `on_click` | `Script [polling]` | `null` | Runs the script when the module is clicked. |
|
||||
| `tooltip` | `string` | `null` | Shows this text on hover. Supports embedding scripts between `{{double braces}}`. |
|
||||
| Name | Type | Default | Description |
|
||||
|-------------------|--------------------|---------|--------------------------------------------------------------------------------------------------------------------|
|
||||
| `show_if` | `Script [polling]` | `null` | Polls the script to check its exit code. If exit code is zero, the module is shown. For other codes, it is hidden. |
|
||||
| `on_click_left` | `Script [oneshot]` | `null` | Runs the script when the module is left clicked. |
|
||||
| `on_click_middle` | `Script [oneshot]` | `null` | Runs the script when the module is middle clicked. |
|
||||
| `on_click_right` | `Script [oneshot]` | `null` | Runs the script when the module is right clicked. |
|
||||
| `on_scroll_up` | `Script [oneshot]` | `null` | Runs the script when the module is scroll up on. |
|
||||
| `on_scroll_down` | `Script [oneshot]` | `null` | Runs the script when the module is scrolled down on. |
|
||||
| `tooltip` | `string` | `null` | Shows this text on hover. Supports embedding scripts between `{{double braces}}`. |
|
||||
|
|
|
@ -3,13 +3,16 @@ that allow script input to dynamically set values.
|
|||
|
||||
Scripts are passed to `sh -c`.
|
||||
|
||||
Two types of scripts exist: polling and watching:
|
||||
Three types of scripts exist: polling, oneshot and watching:
|
||||
|
||||
- Polling scripts will run and wait for exit.
|
||||
- **Polling** scripts will run and wait for exit.
|
||||
Normally they will repeat this at an interval, hence the name, although in some cases they may only run on a user
|
||||
event.
|
||||
If the script exited code 0, the `stdout` will be used. Otherwise, `stderr` will be printed to the log.
|
||||
- Watching scripts start a long-running process. Every time the process writes to `stdout`, the last line is captured
|
||||
- **Oneshot** scripts are a variant of polling scripts.
|
||||
They wait for script to exit, and may do something with the output, but are only fired by user events instead of the interval.
|
||||
Generally options that accept oneshot scripts do not support the other types.
|
||||
- **Watching** scripts start a long-running process. Every time the process writes to `stdout`, the last line is captured
|
||||
and used.
|
||||
|
||||
One should prefer to use watch-mode where possible, as it removes the overhead of regularly spawning processes.
|
||||
|
@ -28,6 +31,8 @@ spawning the script.
|
|||
Both `mode` and `interval` are optional and can be excluded to fall back to their defaults of `poll` and `5000`
|
||||
respectively.
|
||||
|
||||
For oneshot scripts, both the mode and interval are ignored.
|
||||
|
||||
### Shorthand (string)
|
||||
|
||||
Shorthand scripts should be written in the format:
|
||||
|
|
54
src/bar.rs
54
src/bar.rs
|
@ -6,7 +6,7 @@ use crate::popup::Popup;
|
|||
use crate::script::{OutputStream, Script};
|
||||
use crate::{await_sync, read_lock, send, write_lock, Config};
|
||||
use color_eyre::Result;
|
||||
use gtk::gdk::Monitor;
|
||||
use gtk::gdk::{EventMask, Monitor, ScrollDirection};
|
||||
use gtk::prelude::*;
|
||||
use gtk::{Application, ApplicationWindow, EventBox, Orientation, Widget};
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
@ -313,6 +313,7 @@ fn setup_receiver<TSend>(
|
|||
/// The event box container is returned.
|
||||
fn wrap_widget<W: IsA<Widget>>(widget: &W) -> EventBox {
|
||||
let container = EventBox::new();
|
||||
container.add_events(EventMask::SCROLL_MASK);
|
||||
container.add(widget);
|
||||
container
|
||||
}
|
||||
|
@ -345,18 +346,55 @@ fn setup_module_common_options(container: EventBox, common: CommonConfig) {
|
|||
},
|
||||
);
|
||||
|
||||
if let Some(on_click) = common.on_click {
|
||||
let script = Script::new_polling(on_click);
|
||||
container.connect_button_press_event(move |_, _| {
|
||||
trace!("Running on-click script");
|
||||
let left_click_script = common.on_click_left.map(Script::new_polling);
|
||||
let middle_click_script = common.on_click_middle.map(Script::new_polling);
|
||||
let right_click_script = common.on_click_right.map(Script::new_polling);
|
||||
|
||||
container.connect_button_press_event(move |_, event| {
|
||||
let script = match event.button() {
|
||||
1 => left_click_script.as_ref(),
|
||||
2 => middle_click_script.as_ref(),
|
||||
3 => right_click_script.as_ref(),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(script) = script {
|
||||
trace!("Running on-click script: {}", event.button());
|
||||
|
||||
match await_sync(async { script.get_output().await }) {
|
||||
Ok((OutputStream::Stderr(out), _)) => error!("{out}"),
|
||||
Err(err) => error!("{err:?}"),
|
||||
_ => {}
|
||||
}
|
||||
Inhibit(false)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Inhibit(false)
|
||||
});
|
||||
|
||||
let scroll_up_script = common.on_scroll_up.map(Script::new_polling);
|
||||
let scroll_down_script = common.on_scroll_down.map(Script::new_polling);
|
||||
|
||||
container.connect_scroll_event(move |_, event| {
|
||||
println!("{:?}", event.direction());
|
||||
|
||||
let script = match event.direction() {
|
||||
ScrollDirection::Up => scroll_up_script.as_ref(),
|
||||
ScrollDirection::Down => scroll_down_script.as_ref(),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(script) = script {
|
||||
trace!("Running on-scroll script: {}", event.direction());
|
||||
|
||||
match await_sync(async { script.get_output().await }) {
|
||||
Ok((OutputStream::Stderr(out), _)) => error!("{out}"),
|
||||
Err(err) => error!("{err:?}"),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
Inhibit(false)
|
||||
});
|
||||
|
||||
if let Some(tooltip) = common.tooltip {
|
||||
DynamicString::new(&tooltip, move |string| {
|
||||
|
|
|
@ -1,51 +1,14 @@
|
|||
use crate::modules::clock::ClockModule;
|
||||
use crate::modules::custom::CustomModule;
|
||||
use crate::modules::focused::FocusedModule;
|
||||
use crate::modules::launcher::LauncherModule;
|
||||
use crate::modules::mpd::MpdModule;
|
||||
use crate::modules::script::ScriptModule;
|
||||
use crate::modules::sysinfo::SysInfoModule;
|
||||
use crate::modules::tray::TrayModule;
|
||||
use crate::modules::workspaces::WorkspacesModule;
|
||||
use crate::script::ScriptInput;
|
||||
use color_eyre::eyre::{Context, ContextCompat};
|
||||
use color_eyre::{eyre, Help, Report};
|
||||
use super::{BarPosition, Config, MonitorConfig};
|
||||
use color_eyre::eyre::Result;
|
||||
use color_eyre::eyre::{ContextCompat, WrapErr};
|
||||
use color_eyre::{Help, Report};
|
||||
use dirs::config_dir;
|
||||
use eyre::Result;
|
||||
use gtk::Orientation;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use std::collections::HashMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{env, fs};
|
||||
use tracing::instrument;
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct CommonConfig {
|
||||
pub show_if: Option<ScriptInput>,
|
||||
pub on_click: Option<ScriptInput>,
|
||||
pub tooltip: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
pub enum ModuleConfig {
|
||||
Clock(ClockModule),
|
||||
Mpd(MpdModule),
|
||||
Tray(TrayModule),
|
||||
Workspaces(WorkspacesModule),
|
||||
SysInfo(SysInfoModule),
|
||||
Launcher(LauncherModule),
|
||||
Script(ScriptModule),
|
||||
Focused(FocusedModule),
|
||||
Custom(CustomModule),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum MonitorConfig {
|
||||
Single(Config),
|
||||
Multiple(Vec<Config>),
|
||||
}
|
||||
|
||||
// Manually implement for better untagged enum error handling:
|
||||
// currently open pr: https://github.com/serde-rs/serde/pull/1544
|
||||
impl<'de> Deserialize<'de> for MonitorConfig {
|
||||
|
@ -78,21 +41,6 @@ impl<'de> Deserialize<'de> for MonitorConfig {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Copy, Clone, PartialEq, Eq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum BarPosition {
|
||||
Top,
|
||||
Bottom,
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
impl Default for BarPosition {
|
||||
fn default() -> Self {
|
||||
Self::Bottom
|
||||
}
|
||||
}
|
||||
|
||||
impl BarPosition {
|
||||
/// Gets the orientation the bar and widgets should use
|
||||
/// based on this position.
|
||||
|
@ -115,30 +63,6 @@ impl BarPosition {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct Config {
|
||||
#[serde(default = "default_bar_position")]
|
||||
pub position: BarPosition,
|
||||
#[serde(default = "default_true")]
|
||||
pub anchor_to_edges: bool,
|
||||
#[serde(default = "default_bar_height")]
|
||||
pub height: i32,
|
||||
|
||||
pub start: Option<Vec<ModuleConfig>>,
|
||||
pub center: Option<Vec<ModuleConfig>>,
|
||||
pub end: Option<Vec<ModuleConfig>>,
|
||||
|
||||
pub monitors: Option<HashMap<String, MonitorConfig>>,
|
||||
}
|
||||
|
||||
const fn default_bar_position() -> BarPosition {
|
||||
BarPosition::Bottom
|
||||
}
|
||||
|
||||
const fn default_bar_height() -> i32 {
|
||||
42
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Attempts to load the config file from file,
|
||||
/// parse it and return a new instance of `Self`.
|
||||
|
@ -214,10 +138,3 @@ impl Config {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn default_false() -> bool {
|
||||
false
|
||||
}
|
||||
pub const fn default_true() -> bool {
|
||||
true
|
||||
}
|
94
src/config/mod.rs
Normal file
94
src/config/mod.rs
Normal file
|
@ -0,0 +1,94 @@
|
|||
mod r#impl;
|
||||
|
||||
use crate::modules::clock::ClockModule;
|
||||
use crate::modules::custom::CustomModule;
|
||||
use crate::modules::focused::FocusedModule;
|
||||
use crate::modules::launcher::LauncherModule;
|
||||
use crate::modules::mpd::MpdModule;
|
||||
use crate::modules::script::ScriptModule;
|
||||
use crate::modules::sysinfo::SysInfoModule;
|
||||
use crate::modules::tray::TrayModule;
|
||||
use crate::modules::workspaces::WorkspacesModule;
|
||||
use crate::script::ScriptInput;
|
||||
use serde::Deserialize;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct CommonConfig {
|
||||
pub show_if: Option<ScriptInput>,
|
||||
|
||||
pub on_click_left: Option<ScriptInput>,
|
||||
pub on_click_right: Option<ScriptInput>,
|
||||
pub on_click_middle: Option<ScriptInput>,
|
||||
pub on_scroll_up: Option<ScriptInput>,
|
||||
pub on_scroll_down: Option<ScriptInput>,
|
||||
|
||||
pub tooltip: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
pub enum ModuleConfig {
|
||||
Clock(ClockModule),
|
||||
Mpd(MpdModule),
|
||||
Tray(TrayModule),
|
||||
Workspaces(WorkspacesModule),
|
||||
SysInfo(SysInfoModule),
|
||||
Launcher(LauncherModule),
|
||||
Script(ScriptModule),
|
||||
Focused(FocusedModule),
|
||||
Custom(CustomModule),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum MonitorConfig {
|
||||
Single(Config),
|
||||
Multiple(Vec<Config>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Copy, Clone, PartialEq, Eq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum BarPosition {
|
||||
Top,
|
||||
Bottom,
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
impl Default for BarPosition {
|
||||
fn default() -> Self {
|
||||
Self::Bottom
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct Config {
|
||||
#[serde(default = "default_bar_position")]
|
||||
pub position: BarPosition,
|
||||
#[serde(default = "default_true")]
|
||||
pub anchor_to_edges: bool,
|
||||
#[serde(default = "default_bar_height")]
|
||||
pub height: i32,
|
||||
|
||||
pub start: Option<Vec<ModuleConfig>>,
|
||||
pub center: Option<Vec<ModuleConfig>>,
|
||||
pub end: Option<Vec<ModuleConfig>>,
|
||||
|
||||
pub monitors: Option<HashMap<String, MonitorConfig>>,
|
||||
}
|
||||
|
||||
const fn default_bar_position() -> BarPosition {
|
||||
BarPosition::Bottom
|
||||
}
|
||||
|
||||
const fn default_bar_height() -> i32 {
|
||||
42
|
||||
}
|
||||
|
||||
pub const fn default_false() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
pub const fn default_true() -> bool {
|
||||
true
|
||||
}
|
Loading…
Add table
Reference in a new issue