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

config: make focus-follows-mouse optional #187

Merged
merged 1 commit into from
Apr 27, 2024
Merged
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
2 changes: 2 additions & 0 deletions deploy-notes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Unreleased

- Needs jay-config release.
- Needs jay-toml-config release.
- Needs jay-compositor release.

# 1.1.0
Expand Down
9 changes: 8 additions & 1 deletion jay-config/src/_private/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ use {
logging, Config, ConfigEntry, ConfigEntryGen, PollableId, WireMode, VERSION,
},
exec::Command,
input::{acceleration::AccelProfile, capability::Capability, InputDevice, Seat},
input::{
acceleration::AccelProfile, capability::Capability, FocusFollowsMouseMode, InputDevice,
Seat,
},
keyboard::{
mods::{Modifiers, RELEASE},
syms::KeySym,
Expand Down Expand Up @@ -924,6 +927,10 @@ impl Client {
self.send(&ClientMessage::SetForward { seat, forward })
}

pub fn set_focus_follows_mouse_mode(&self, seat: Seat, mode: FocusFollowsMouseMode) {
self.send(&ClientMessage::SetFocusFollowsMouseMode { seat, mode })
}

pub fn parse_keymap(&self, keymap: &str) -> Keymap {
let res = self.send_with_response(&ClientMessage::ParseKeymap { keymap });
get_response!(res, Keymap(0), ParseKeymap { keymap });
Expand Down
9 changes: 8 additions & 1 deletion jay-config/src/_private/ipc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use {
crate::{
input::{acceleration::AccelProfile, capability::Capability, InputDevice, Seat},
input::{
acceleration::AccelProfile, capability::Capability, FocusFollowsMouseMode, InputDevice,
Seat,
},
keyboard::{mods::Modifiers, syms::KeySym, Keymap},
logging::LogLevel,
theme::{colors::Colorable, sized::Resizable, Color},
Expand Down Expand Up @@ -464,6 +467,10 @@ pub enum ClientMessage<'a> {
mod_mask: Modifiers,
sym: KeySym,
},
SetFocusFollowsMouseMode {
seat: Seat,
mode: FocusFollowsMouseMode,
},
}

#[derive(Serialize, Deserialize, Debug)]
Expand Down
15 changes: 15 additions & 0 deletions jay-config/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,21 @@ impl Seat {
pub fn consume(self) {
self.set_forward(false)
}

/// Sets the focus-follows-mouse mode.
pub fn set_focus_follows_mouse_mode(self, mode: FocusFollowsMouseMode) {
get!().set_focus_follows_mouse_mode(self, mode);
}
}

/// A focus-follows-mouse mode.
#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum FocusFollowsMouseMode {
/// When the mouse moves and enters a toplevel, that toplevel gets the keyboard focus.
True,
/// The keyboard focus changes only when clicking on a window or the previously
/// focused window becomes invisible.
False,
}

/// Returns all seats.
Expand Down
1 change: 1 addition & 0 deletions release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- Add support for xdg-dialog-v1.
- Add support for ext-transient-seat-v1.
- Add support for wp-drm-lease-v1.
- Focus-follows-mouse can now be disabled.

# 1.1.0 (2024-04-22)

Expand Down
19 changes: 18 additions & 1 deletion src/config/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use {
Capability, CAP_GESTURE, CAP_KEYBOARD, CAP_POINTER, CAP_SWITCH, CAP_TABLET_PAD,
CAP_TABLET_TOOL, CAP_TOUCH,
},
InputDevice, Seat,
FocusFollowsMouseMode, InputDevice, Seat,
},
keyboard::{mods::Modifiers, syms::KeySym, Keymap},
logging::LogLevel,
Expand Down Expand Up @@ -324,6 +324,20 @@ impl ConfigProxyHandler {
Ok(())
}

fn handle_set_focus_follows_mouse_mode(
&self,
seat: Seat,
mode: FocusFollowsMouseMode,
) -> Result<(), CphError> {
let seat = self.get_seat(seat)?;
let focus_follows_mouse = match mode {
FocusFollowsMouseMode::True => true,
FocusFollowsMouseMode::False => false,
};
seat.set_focus_follows_mouse(focus_follows_mouse);
Ok(())
}

fn handle_set_status(&self, status: &str) {
self.state.set_status(status);
}
Expand Down Expand Up @@ -1791,6 +1805,9 @@ impl ConfigProxyHandler {
} => self
.handle_add_shortcut(seat, mod_mask, mods, sym)
.wrn("add_shortcut")?,
ClientMessage::SetFocusFollowsMouseMode { seat, mode } => self
.handle_set_focus_follows_mouse_mode(seat, mode)
.wrn("set_focus_follows_mouse_mode")?,
}
Ok(())
}
Expand Down
6 changes: 6 additions & 0 deletions src/ifs/wl_seat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ pub struct WlSeatGlobal {
input_method: CloneCell<Option<Rc<ZwpInputMethodV2>>>,
input_method_grab: CloneCell<Option<Rc<ZwpInputMethodKeyboardGrabV2>>>,
forward: Cell<bool>,
focus_follows_mouse: Cell<bool>,
}

const CHANGE_CURSOR_MOVED: u32 = 1 << 0;
Expand Down Expand Up @@ -250,6 +251,7 @@ impl WlSeatGlobal {
input_method: Default::default(),
input_method_grab: Default::default(),
forward: Cell::new(false),
focus_follows_mouse: Cell::new(true),
});
state.add_cursor_size(*DEFAULT_CURSOR_SIZE);
let seat = slf.clone();
Expand Down Expand Up @@ -1165,6 +1167,10 @@ impl WlSeatGlobal {
pub fn select_workspace(self: &Rc<Self>, selector: impl WorkspaceSelector) {
self.pointer_owner.select_workspace(self, selector);
}

pub fn set_focus_follows_mouse(&self, focus_follows_mouse: bool) {
self.focus_follows_mouse.set(focus_follows_mouse);
}
}

global_base!(WlSeatGlobal, WlSeat, WlSeatError);
Expand Down
5 changes: 4 additions & 1 deletion src/ifs/wl_seat/event_handling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -756,7 +756,10 @@ impl WlSeatGlobal {
// Enter callbacks
impl WlSeatGlobal {
pub fn enter_toplevel(self: &Rc<Self>, n: Rc<dyn ToplevelNode>) {
if n.tl_accepts_keyboard_focus() && self.changes.get().contains(CHANGE_CURSOR_MOVED) {
if n.tl_accepts_keyboard_focus()
&& self.changes.get().contains(CHANGE_CURSOR_MOVED)
&& self.focus_follows_mouse.get()
{
self.focus_toplevel(n);
}
}
Expand Down
1 change: 1 addition & 0 deletions toml-config/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ pub struct Config {
pub inputs: Vec<Input>,
pub idle: Option<Duration>,
pub explicit_sync_enabled: Option<bool>,
pub focus_follows_mouse: bool,
}

#[derive(Debug, Error)]
Expand Down
4 changes: 3 additions & 1 deletion toml-config/src/config/parsers/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ impl Parser for ConfigParser<'_> {
_,
idle_val,
),
(explicit_sync, repeat_rate_val, complex_shortcuts_val),
(explicit_sync, repeat_rate_val, complex_shortcuts_val, focus_follows_mouse),
) = ext.extract((
(
opt(val("keymap")),
Expand Down Expand Up @@ -127,6 +127,7 @@ impl Parser for ConfigParser<'_> {
recover(opt(bol("explicit-sync"))),
opt(val("repeat-rate")),
opt(val("complex-shortcuts")),
recover(opt(bol("focus-follows-mouse"))),
),
))?;
let mut keymap = None;
Expand Down Expand Up @@ -307,6 +308,7 @@ impl Parser for ConfigParser<'_> {
render_device,
inputs,
idle,
focus_follows_mouse: focus_follows_mouse.despan().unwrap_or(true),
})
}
}
10 changes: 9 additions & 1 deletion toml-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ use {
config, config_dir,
exec::{set_env, unset_env, Command},
get_workspace,
input::{get_seat, input_devices, on_new_input_device, InputDevice, Seat},
input::{
get_seat, input_devices, on_new_input_device, FocusFollowsMouseMode, InputDevice, Seat,
},
is_reload,
keyboard::{Keymap, ModifiedKeySym},
logging::set_log_level,
Expand Down Expand Up @@ -869,6 +871,12 @@ fn load_config(initial_load: bool, persistent: &Rc<PersistentState>) {
}
}
});
persistent
.seat
.set_focus_follows_mouse_mode(match config.focus_follows_mouse {
true => FocusFollowsMouseMode::True,
false => FocusFollowsMouseMode::False,
});
}

fn create_command(exec: &Exec) -> Command {
Expand Down
4 changes: 4 additions & 0 deletions toml-spec/spec/spec.generated.json
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,10 @@
"idle": {
"description": "The configuration of the idle timeout.\n\nChanging thise field after compositor startup has no effect. Use `jay idle`\nor a `configure-idle` action to change the idle timeout at runtime.\n\n- Example:\n\n ```toml\n idle.minutes = 10\n ```\n",
"$ref": "#/$defs/Idle"
},
"focus-follows-mouse": {
"type": "boolean",
"description": "Configures whether moving the mouse over a window automatically moves the keyboard\nfocus to that window.\n\nThe default is `true`.\n"
}
},
"required": []
Expand Down
9 changes: 9 additions & 0 deletions toml-spec/spec/spec.generated.md
Original file line number Diff line number Diff line change
Expand Up @@ -1086,6 +1086,15 @@ The table has the following fields:

The value of this field should be a [Idle](#types-Idle).

- `focus-follows-mouse` (optional):

Configures whether moving the mouse over a window automatically moves the keyboard
focus to that window.

The default is `true`.

The value of this field should be a boolean.


<a name="types-Connector"></a>
### `Connector`
Expand Down
8 changes: 8 additions & 0 deletions toml-spec/spec/spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2039,6 +2039,14 @@ Config:
```toml
idle.minutes = 10
```
focus-follows-mouse:
kind: boolean
required: false
description: |
Configures whether moving the mouse over a window automatically moves the keyboard
focus to that window.

The default is `true`.


Idle:
Expand Down
Loading