mirror of
				https://github.com/Zedfrigg/ironbar.git
				synced 2025-11-03 23:11:54 +01:00 
			
		
		
		
	feat: ability to set bar layer and exclusive zone
This commit is contained in:
		
					parent
					
						
							
								c28de8d902
							
						
					
				
			
			
				commit
				
					
						aa45396062
					
				
			
		
					 7 changed files with 145 additions and 36 deletions
				
			
		| 
						 | 
				
			
			@ -296,16 +296,18 @@ The following table lists each of the top-level bar config options:
 | 
			
		|||
The following table lists each of the bar-level bar config options:
 | 
			
		||||
 | 
			
		||||
| Name              | Type                                           | Default                                  | Description                                                                                                                |
 | 
			
		||||
|-------------------|----------------------------------------|--------------------------------------|----------------------------------------------------------------------------------------------------------------------------|
 | 
			
		||||
|-------------------|------------------------------------------------|------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|
 | 
			
		||||
| `name`            | `string`                                       | `bar-<n>`                                | A unique identifier for the bar, used for controlling it over IPC. If not set, uses a generated integer suffix.            |
 | 
			
		||||
| `position`        | `top` or `bottom` or `left` or `right`         | `bottom`                                 | The bar's position on screen.                                                                                              |
 | 
			
		||||
| `anchor_to_edges` | `boolean`                                      | `false`                                  | Whether to anchor the bar to the edges of the screen. Setting to false centres the bar.                                    |
 | 
			
		||||
| `height`          | `integer`                                      | `42`                                     | The bar's height in pixels.                                                                                                |
 | 
			
		||||
| `popup_gap`       | `integer`                              | `5`                                  | The gap between the bar and popup window.                                                                                  |
 | 
			
		||||
| `margin.top`      | `integer`                                      | `0`                                      | The margin on the top of the bar                                                                                           |
 | 
			
		||||
| `margin.bottom`   | `integer`                                      | `0`                                      | The margin on the bottom of the bar                                                                                        |
 | 
			
		||||
| `margin.left`     | `integer`                                      | `0`                                      | The margin on the left of the bar                                                                                          |
 | 
			
		||||
| `margin.right`    | `integer`                                      | `0`                                      | The margin on the right of the bar                                                                                         |
 | 
			
		||||
| `layer`           | `background` or `bottom` or `top` or `overlay` | `top`                                    | The layer-shell layer to place the bar on.                                                                                 |
 | 
			
		||||
| `exclusive_zone`  | `boolean`                                      | `true` unless `start_hidden` is enabled. | Whether the bar should reserve an exclusive zone around it.                                                                |
 | 
			
		||||
| `popup_gap`       | `integer`                                      | `5`                                      | The gap between the bar and popup window.                                                                                  |
 | 
			
		||||
| `icon_theme`      | `string`                                       | `null`                                   | Name of the GTK icon theme to use. Leave blank to use default.                                                             |
 | 
			
		||||
| `start_hidden`    | `boolean`                                      | `false`, or `true` if `autohide` set     | Whether the bar should be hidden when the application starts. Enabled by default when `autohide` is set.                   |
 | 
			
		||||
| `autohide`        | `integer`                                      | `null`                                   | The duration in milliseconds before the bar is hidden after the cursor leaves. Leave unset to disable auto-hide behaviour. |
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -289,6 +289,18 @@ Gets the popup's current visibility state.
 | 
			
		|||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### `set_exclusive`
 | 
			
		||||
 | 
			
		||||
Sets whether the bar reserves an exclusive zone.
 | 
			
		||||
 | 
			
		||||
```json
 | 
			
		||||
{
 | 
			
		||||
  "command": "bar",
 | 
			
		||||
  "subcommand": "set_exclusive",
 | 
			
		||||
  "exclusive": true
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Responses
 | 
			
		||||
 | 
			
		||||
### `ok`
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										48
									
								
								src/bar.rs
									
										
									
									
									
								
							
							
						
						
									
										48
									
								
								src/bar.rs
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -120,27 +120,28 @@ impl Bar {
 | 
			
		|||
            self.name, self.monitor_name
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        self.setup_layer_shell(
 | 
			
		||||
            &self.window,
 | 
			
		||||
            true,
 | 
			
		||||
            config.anchor_to_edges,
 | 
			
		||||
            config.margin,
 | 
			
		||||
            monitor,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        let start_hidden = config
 | 
			
		||||
            .start_hidden
 | 
			
		||||
            .unwrap_or_else(|| config.autohide.is_some());
 | 
			
		||||
 | 
			
		||||
        self.setup_layer_shell(
 | 
			
		||||
            &self.window,
 | 
			
		||||
            config.exclusive_zone.unwrap_or(!start_hidden),
 | 
			
		||||
            config.anchor_to_edges,
 | 
			
		||||
            config.margin,
 | 
			
		||||
            config.layer,
 | 
			
		||||
            monitor,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        if let Some(autohide) = config.autohide {
 | 
			
		||||
            let hotspot_window = Window::new(WindowType::Toplevel);
 | 
			
		||||
 | 
			
		||||
            Self::setup_autohide(&self.window, &hotspot_window, autohide);
 | 
			
		||||
            self.setup_layer_shell(
 | 
			
		||||
                &hotspot_window,
 | 
			
		||||
                false,
 | 
			
		||||
                config.anchor_to_edges,
 | 
			
		||||
                config.margin,
 | 
			
		||||
                gtk_layer_shell::Layer::Top,
 | 
			
		||||
                monitor,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -166,43 +167,46 @@ impl Bar {
 | 
			
		|||
        exclusive_zone: bool,
 | 
			
		||||
        anchor_to_edges: bool,
 | 
			
		||||
        margin: MarginConfig,
 | 
			
		||||
        layer: gtk_layer_shell::Layer,
 | 
			
		||||
        monitor: &Monitor,
 | 
			
		||||
    ) {
 | 
			
		||||
        use gtk_layer_shell::Edge;
 | 
			
		||||
 | 
			
		||||
        let position = self.position;
 | 
			
		||||
 | 
			
		||||
        win.init_layer_shell();
 | 
			
		||||
        win.set_monitor(monitor);
 | 
			
		||||
        win.set_layer(gtk_layer_shell::Layer::Top);
 | 
			
		||||
        win.set_layer(layer);
 | 
			
		||||
        win.set_namespace(env!("CARGO_PKG_NAME"));
 | 
			
		||||
 | 
			
		||||
        if exclusive_zone {
 | 
			
		||||
            win.auto_exclusive_zone_enable();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        win.set_layer_shell_margin(gtk_layer_shell::Edge::Top, margin.top);
 | 
			
		||||
        win.set_layer_shell_margin(gtk_layer_shell::Edge::Bottom, margin.bottom);
 | 
			
		||||
        win.set_layer_shell_margin(gtk_layer_shell::Edge::Left, margin.left);
 | 
			
		||||
        win.set_layer_shell_margin(gtk_layer_shell::Edge::Right, margin.right);
 | 
			
		||||
        win.set_layer_shell_margin(Edge::Top, margin.top);
 | 
			
		||||
        win.set_layer_shell_margin(Edge::Bottom, margin.bottom);
 | 
			
		||||
        win.set_layer_shell_margin(Edge::Left, margin.left);
 | 
			
		||||
        win.set_layer_shell_margin(Edge::Right, margin.right);
 | 
			
		||||
 | 
			
		||||
        let bar_orientation = position.orientation();
 | 
			
		||||
 | 
			
		||||
        win.set_anchor(
 | 
			
		||||
            gtk_layer_shell::Edge::Top,
 | 
			
		||||
            Edge::Top,
 | 
			
		||||
            position == BarPosition::Top
 | 
			
		||||
                || (bar_orientation == Orientation::Vertical && anchor_to_edges),
 | 
			
		||||
        );
 | 
			
		||||
        win.set_anchor(
 | 
			
		||||
            gtk_layer_shell::Edge::Bottom,
 | 
			
		||||
            Edge::Bottom,
 | 
			
		||||
            position == BarPosition::Bottom
 | 
			
		||||
                || (bar_orientation == Orientation::Vertical && anchor_to_edges),
 | 
			
		||||
        );
 | 
			
		||||
        win.set_anchor(
 | 
			
		||||
            gtk_layer_shell::Edge::Left,
 | 
			
		||||
            Edge::Left,
 | 
			
		||||
            position == BarPosition::Left
 | 
			
		||||
                || (bar_orientation == Orientation::Horizontal && anchor_to_edges),
 | 
			
		||||
        );
 | 
			
		||||
        win.set_anchor(
 | 
			
		||||
            gtk_layer_shell::Edge::Right,
 | 
			
		||||
            Edge::Right,
 | 
			
		||||
            position == BarPosition::Right
 | 
			
		||||
                || (bar_orientation == Orientation::Horizontal && anchor_to_edges),
 | 
			
		||||
        );
 | 
			
		||||
| 
						 | 
				
			
			@ -329,6 +333,14 @@ impl Bar {
 | 
			
		|||
    pub fn set_visible(&self, visible: bool) {
 | 
			
		||||
        self.window.set_visible(visible)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn set_exclusive(&self, exclusive: bool) {
 | 
			
		||||
        if exclusive {
 | 
			
		||||
            self.window.auto_exclusive_zone_enable();
 | 
			
		||||
        } else {
 | 
			
		||||
            self.window.set_exclusive_zone(0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Creates a `gtk::Box` container to place widgets inside.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,6 +35,37 @@ impl<'de> Deserialize<'de> for MonitorConfig {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn deserialize_layer<'de, D>(deserializer: D) -> Result<gtk_layer_shell::Layer, D::Error>
 | 
			
		||||
where
 | 
			
		||||
    D: serde::Deserializer<'de>,
 | 
			
		||||
{
 | 
			
		||||
    use gtk_layer_shell::Layer;
 | 
			
		||||
 | 
			
		||||
    let value = Option::<String>::deserialize(deserializer)?;
 | 
			
		||||
    value
 | 
			
		||||
        .map(|v| match v.as_str() {
 | 
			
		||||
            "background" => Ok(Layer::Background),
 | 
			
		||||
            "bottom" => Ok(Layer::Bottom),
 | 
			
		||||
            "top" => Ok(Layer::Top),
 | 
			
		||||
            "overlay" => Ok(Layer::Overlay),
 | 
			
		||||
            _ => Err(serde::de::Error::custom("invalid value for orientation")),
 | 
			
		||||
        })
 | 
			
		||||
        .unwrap_or(Ok(Layer::Top))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(feature = "schema")]
 | 
			
		||||
pub fn schema_layer(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
 | 
			
		||||
    use schemars::JsonSchema;
 | 
			
		||||
    let mut schema: schemars::schema::SchemaObject = <String>::json_schema(gen).into();
 | 
			
		||||
    schema.enum_values = Some(vec![
 | 
			
		||||
        "background".into(),
 | 
			
		||||
        "bottom".into(),
 | 
			
		||||
        "top".into(),
 | 
			
		||||
        "overlay".into(),
 | 
			
		||||
    ]);
 | 
			
		||||
    schema.into()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl BarPosition {
 | 
			
		||||
    /// Gets the orientation the bar and widgets should use
 | 
			
		||||
    /// based on this position.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -216,6 +216,36 @@ pub struct BarConfig {
 | 
			
		|||
    #[serde(default)]
 | 
			
		||||
    pub margin: MarginConfig,
 | 
			
		||||
 | 
			
		||||
    /// The layer-shell layer to place the bar on.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Taken from the
 | 
			
		||||
    /// [wlr_layer_shell](https://wayland.app/protocols/wlr-layer-shell-unstable-v1#zwlr_layer_shell_v1:enum:layer) definition:
 | 
			
		||||
    ///
 | 
			
		||||
    /// > These values indicate which layers a surface can be rendered in.
 | 
			
		||||
    /// > They are ordered by z depth, bottom-most first.
 | 
			
		||||
    /// > Traditional shell surfaces will typically be rendered between the bottom and top layers.
 | 
			
		||||
    /// > Fullscreen shell surfaces are typically rendered at the top layer.
 | 
			
		||||
    /// > Multiple surfaces can share a single layer, and ordering within a single layer is undefined.
 | 
			
		||||
    ///
 | 
			
		||||
    /// **Valid options**: `background`, `bottom`, `top`, `overlay`
 | 
			
		||||
    /// <br>
 | 
			
		||||
    /// **Default**: `top`
 | 
			
		||||
    #[serde(
 | 
			
		||||
        default = "default_layer",
 | 
			
		||||
        deserialize_with = "r#impl::deserialize_layer"
 | 
			
		||||
    )]
 | 
			
		||||
    #[cfg_attr(feature = "schema", schemars(schema_with = "r#impl::schema_layer"))]
 | 
			
		||||
    pub layer: gtk_layer_shell::Layer,
 | 
			
		||||
 | 
			
		||||
    /// Whether the bar should reserve an exclusive zone around it.
 | 
			
		||||
    ///
 | 
			
		||||
    /// When true, this prevents windows from rendering in the same space
 | 
			
		||||
    /// as the bar, causing them to shift.
 | 
			
		||||
    ///
 | 
			
		||||
    /// **Default**: `true` unless `start_hidden` is set.
 | 
			
		||||
    #[serde(default)]
 | 
			
		||||
    pub exclusive_zone: Option<bool>,
 | 
			
		||||
 | 
			
		||||
    /// The size of the gap in pixels
 | 
			
		||||
    /// between the bar and the popup window.
 | 
			
		||||
    ///
 | 
			
		||||
| 
						 | 
				
			
			@ -282,9 +312,11 @@ impl Default for BarConfig {
 | 
			
		|||
 | 
			
		||||
        Self {
 | 
			
		||||
            position: BarPosition::default(),
 | 
			
		||||
            height: default_bar_height(),
 | 
			
		||||
            margin: MarginConfig::default(),
 | 
			
		||||
            name: None,
 | 
			
		||||
            layer: default_layer(),
 | 
			
		||||
            exclusive_zone: None,
 | 
			
		||||
            height: default_bar_height(),
 | 
			
		||||
            start_hidden: None,
 | 
			
		||||
            autohide: None,
 | 
			
		||||
            icon_theme: None,
 | 
			
		||||
| 
						 | 
				
			
			@ -340,6 +372,10 @@ pub struct Config {
 | 
			
		|||
    pub monitors: Option<HashMap<String, MonitorConfig>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const fn default_layer() -> gtk_layer_shell::Layer {
 | 
			
		||||
    gtk_layer_shell::Layer::Top
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const fn default_bar_height() -> i32 {
 | 
			
		||||
    42
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -118,4 +118,15 @@ pub enum BarCommandType {
 | 
			
		|||
    },
 | 
			
		||||
    /// Get the popup's current visibility state.
 | 
			
		||||
    GetPopupVisible,
 | 
			
		||||
 | 
			
		||||
    // == Exclusivity == \\
 | 
			
		||||
    /// Set whether the bar reserves an exclusive zone.
 | 
			
		||||
    SetExclusive {
 | 
			
		||||
        #[clap(
 | 
			
		||||
            num_args(1),
 | 
			
		||||
            require_equals(true),
 | 
			
		||||
            action = ArgAction::Set,
 | 
			
		||||
        )]
 | 
			
		||||
        exclusive: bool,
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,6 +43,11 @@ pub fn handle_command(command: BarCommand, ironbar: &Rc<Ironbar>) -> Response {
 | 
			
		|||
        GetPopupVisible => Response::OkValue {
 | 
			
		||||
            value: bar.popup().visible().to_string(),
 | 
			
		||||
        },
 | 
			
		||||
        SetExclusive { exclusive } => {
 | 
			
		||||
            bar.set_exclusive(exclusive);
 | 
			
		||||
 | 
			
		||||
            Response::Ok
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue