Skip to content

Commit

Permalink
feat: Add support for on-demand window focus on wayland (#1215)
Browse files Browse the repository at this point in the history
* feat: Add support for on-demand window focus on wayland

* fix: cargo fmt

* Update CHANGELOG.md with OnDemand focusable

* fix: add v0_6 feature to gtk-layer-shell in eww/cargo.toml
  • Loading branch information
GallowsDove authored Dec 26, 2024
1 parent 95124ad commit 2c81b3f
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ All notable changes to eww will be listed here, starting at changes since versio
- Fix wayland monitor names support (By: dragonnn)

### Features
- Add OnDemand support for focusable on wayland (By: GallowsDove)
- Update rust toolchain to 1.81.0 (By: w-lfchen)
- Add `:fill-svg` and `:preserve-aspect-ratio` properties to images (By: hypernova7, w-lfchen)
- Add `:truncate` property to labels, disabled by default (except in cases where truncation would be enabled in version `0.5.0` and before) (By: Rayzeq).
Expand Down
2 changes: 1 addition & 1 deletion crates/eww/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ eww_shared_util.workspace = true
yuck.workspace = true
notifier_host.workspace = true

gtk-layer-shell = { version = "0.8.1", optional = true }
gtk-layer-shell = { version = "0.8.1", optional = true, features=["v0_6"] }
gdkx11 = { version = "0.18", optional = true }
x11rb = { version = "0.13.1", features = ["randr"], optional = true }
gdk-sys = "0.18.0"
Expand Down
12 changes: 8 additions & 4 deletions crates/eww/src/display_backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ impl DisplayBackend for NoBackend {

#[cfg(feature = "wayland")]
mod platform_wayland {
use super::DisplayBackend;
use crate::{widgets::window::Window, window_initiator::WindowInitiator};
use gtk::gdk;
use gtk::prelude::*;
use gtk_layer_shell::LayerShell;
use gtk_layer_shell::{KeyboardMode, LayerShell};
use yuck::config::backend_window_options::WlWindowFocusable;
use yuck::config::{window_definition::WindowStacking, window_geometry::AnchorAlignment};

use super::DisplayBackend;

pub struct WaylandBackend;

impl DisplayBackend for WaylandBackend {
Expand Down Expand Up @@ -70,7 +70,11 @@ mod platform_wayland {
}

// Sets the keyboard interactivity
window.set_keyboard_interactivity(window_init.backend_options.wayland.focusable);
match window_init.backend_options.wayland.focusable {
WlWindowFocusable::None => window.set_keyboard_mode(KeyboardMode::None),
WlWindowFocusable::Exclusive => window.set_keyboard_mode(KeyboardMode::Exclusive),
WlWindowFocusable::OnDemand => window.set_keyboard_mode(KeyboardMode::OnDemand),
}

if let Some(geometry) = window_init.geometry {
// Positioning surface
Expand Down
42 changes: 35 additions & 7 deletions crates/yuck/src/config/backend_window_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ use simplexpr::{
SimplExpr,
};

use super::{attributes::Attributes, window_definition::EnumParseError};
use crate::{
enum_parse,
error::DiagResult,
parser::{ast::Ast, ast_iterator::AstIterator, from_ast::FromAstElementContent},
value::{coords, NumWithUnit},
};
use eww_shared_util::{Span, VarName};

use super::{attributes::Attributes, window_definition::EnumParseError};
use simplexpr::dynval::ConversionError;

use crate::error::{DiagError, DiagResultExt};

Expand All @@ -27,6 +27,8 @@ pub enum Error {
CoordsError(#[from] coords::Error),
#[error(transparent)]
EvalError(#[from] EvalError),
#[error(transparent)]
ConversionError(#[from] ConversionError),
}

/// Backend-specific options of a window
Expand All @@ -45,6 +47,7 @@ impl BackendWindowOptionsDef {
pub fn from_attrs(attrs: &mut Attributes) -> DiagResult<Self> {
let struts = attrs.ast_optional("reserve")?;
let window_type = attrs.ast_optional("windowtype")?;
let focusable = attrs.ast_optional("focusable")?;
let x11 = X11BackendWindowOptionsDef {
sticky: attrs.ast_optional("sticky")?,
struts,
Expand All @@ -53,7 +56,7 @@ impl BackendWindowOptionsDef {
};
let wayland = WlBackendWindowOptionsDef {
exclusive: attrs.ast_optional("exclusive")?,
focusable: attrs.ast_optional("focusable")?,
focusable,
namespace: attrs.ast_optional("namespace")?,
};

Expand Down Expand Up @@ -109,7 +112,7 @@ impl X11BackendWindowOptionsDef {
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
pub struct WlBackendWindowOptions {
pub exclusive: bool,
pub focusable: bool,
pub focusable: WlWindowFocusable,
pub namespace: Option<String>,
}

Expand All @@ -122,10 +125,13 @@ pub struct WlBackendWindowOptionsDef {
}

impl WlBackendWindowOptionsDef {
fn eval(&self, local_variables: &HashMap<VarName, DynVal>) -> Result<WlBackendWindowOptions, EvalError> {
fn eval(&self, local_variables: &HashMap<VarName, DynVal>) -> Result<WlBackendWindowOptions, Error> {
Ok(WlBackendWindowOptions {
exclusive: eval_opt_expr_as_bool(&self.exclusive, false, local_variables)?,
focusable: eval_opt_expr_as_bool(&self.focusable, false, local_variables)?,
focusable: match &self.focusable {
Some(expr) => WlWindowFocusable::from_dynval(&expr.eval(local_variables)?)?,
None => WlWindowFocusable::default(),
},
namespace: match &self.namespace {
Some(expr) => Some(expr.eval(local_variables)?.as_string()?),
None => None,
Expand All @@ -145,6 +151,28 @@ fn eval_opt_expr_as_bool(
})
}

#[derive(Debug, Clone, PartialEq, Eq, smart_default::SmartDefault, serde::Serialize)]
pub enum WlWindowFocusable {
#[default]
None,
Exclusive,
OnDemand,
}
impl FromStr for WlWindowFocusable {
type Err = EnumParseError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
enum_parse! { "focusable", s,
"none" => Self::None,
"exclusive" => Self::Exclusive,
"ondemand" => Self::OnDemand,
// legacy support
"true" => Self::Exclusive,
"false" => Self::None,
}
}
}

/// Window type of an x11 window
#[derive(Debug, Clone, PartialEq, Eq, smart_default::SmartDefault, serde::Serialize)]
pub enum X11WindowType {
Expand Down Expand Up @@ -182,7 +210,7 @@ pub enum Side {
Bottom,
}

impl std::str::FromStr for Side {
impl FromStr for Side {
type Err = EnumParseError;

fn from_str(s: &str) -> Result<Side, Self::Err> {
Expand Down
12 changes: 6 additions & 6 deletions docs/src/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,12 @@ Depending on if you are using X11 or Wayland, some additional properties exist:

#### Wayland

| Property | Description |
| ----------: | ------------------------------------------------------------ |
| `stacking` | Where the window should appear in the stack. Possible values: `fg`, `bg`, `overlay`, `bottom`. |
| `exclusive` | Whether the compositor should reserve space for the window automatically. Either `true` or `false`. |
| `focusable` | Whether the window should be able to be focused. This is necessary for any widgets that use the keyboard to work. Either `true` or `false`. |
| `namespace` | Set the wayland layersurface namespace eww uses. Accepts a `string` value. |
| Property | Description |
| ----------: |------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `stacking` | Where the window should appear in the stack. Possible values: `fg`, `bg`, `overlay`, `bottom`. |
| `exclusive` | Whether the compositor should reserve space for the window automatically. Either `true` or `false`. |
| `focusable` | Whether the window should be able to be focused. This is necessary for any widgets that use the keyboard to work. Possible values: `none`, `exclusive` and `ondemand`. |
| `namespace` | Set the wayland layersurface namespace eww uses. Accepts a `string` value. |



Expand Down
2 changes: 1 addition & 1 deletion examples/data-structures/eww.yuck
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
(defwindow data-structures
:monitor 0
:exclusive false
:focusable false
:focusable none
:geometry (geometry
:anchor "center"
)
Expand Down

0 comments on commit 2c81b3f

Please sign in to comment.