config: make focus-follows-mouse optional
This commit is contained in:
parent
fe2663fca3
commit
a12065a915
14 changed files with 96 additions and 6 deletions
|
|
@ -1,5 +1,7 @@
|
||||||
# Unreleased
|
# Unreleased
|
||||||
|
|
||||||
|
- Needs jay-config release.
|
||||||
|
- Needs jay-toml-config release.
|
||||||
- Needs jay-compositor release.
|
- Needs jay-compositor release.
|
||||||
|
|
||||||
# 1.1.0
|
# 1.1.0
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,10 @@ use {
|
||||||
logging, Config, ConfigEntry, ConfigEntryGen, PollableId, WireMode, VERSION,
|
logging, Config, ConfigEntry, ConfigEntryGen, PollableId, WireMode, VERSION,
|
||||||
},
|
},
|
||||||
exec::Command,
|
exec::Command,
|
||||||
input::{acceleration::AccelProfile, capability::Capability, InputDevice, Seat},
|
input::{
|
||||||
|
acceleration::AccelProfile, capability::Capability, FocusFollowsMouseMode, InputDevice,
|
||||||
|
Seat,
|
||||||
|
},
|
||||||
keyboard::{
|
keyboard::{
|
||||||
mods::{Modifiers, RELEASE},
|
mods::{Modifiers, RELEASE},
|
||||||
syms::KeySym,
|
syms::KeySym,
|
||||||
|
|
@ -924,6 +927,10 @@ impl Client {
|
||||||
self.send(&ClientMessage::SetForward { seat, forward })
|
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 {
|
pub fn parse_keymap(&self, keymap: &str) -> Keymap {
|
||||||
let res = self.send_with_response(&ClientMessage::ParseKeymap { keymap });
|
let res = self.send_with_response(&ClientMessage::ParseKeymap { keymap });
|
||||||
get_response!(res, Keymap(0), ParseKeymap { keymap });
|
get_response!(res, Keymap(0), ParseKeymap { keymap });
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
input::{acceleration::AccelProfile, capability::Capability, InputDevice, Seat},
|
input::{
|
||||||
|
acceleration::AccelProfile, capability::Capability, FocusFollowsMouseMode, InputDevice,
|
||||||
|
Seat,
|
||||||
|
},
|
||||||
keyboard::{mods::Modifiers, syms::KeySym, Keymap},
|
keyboard::{mods::Modifiers, syms::KeySym, Keymap},
|
||||||
logging::LogLevel,
|
logging::LogLevel,
|
||||||
theme::{colors::Colorable, sized::Resizable, Color},
|
theme::{colors::Colorable, sized::Resizable, Color},
|
||||||
|
|
@ -464,6 +467,10 @@ pub enum ClientMessage<'a> {
|
||||||
mod_mask: Modifiers,
|
mod_mask: Modifiers,
|
||||||
sym: KeySym,
|
sym: KeySym,
|
||||||
},
|
},
|
||||||
|
SetFocusFollowsMouseMode {
|
||||||
|
seat: Seat,
|
||||||
|
mode: FocusFollowsMouseMode,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
|
|
||||||
|
|
@ -390,6 +390,21 @@ impl Seat {
|
||||||
pub fn consume(self) {
|
pub fn consume(self) {
|
||||||
self.set_forward(false)
|
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.
|
/// Returns all seats.
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
- Add support for xdg-dialog-v1.
|
- Add support for xdg-dialog-v1.
|
||||||
- Add support for ext-transient-seat-v1.
|
- Add support for ext-transient-seat-v1.
|
||||||
- Add support for wp-drm-lease-v1.
|
- Add support for wp-drm-lease-v1.
|
||||||
|
- Focus-follows-mouse can now be disabled.
|
||||||
|
|
||||||
# 1.1.0 (2024-04-22)
|
# 1.1.0 (2024-04-22)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ use {
|
||||||
Capability, CAP_GESTURE, CAP_KEYBOARD, CAP_POINTER, CAP_SWITCH, CAP_TABLET_PAD,
|
Capability, CAP_GESTURE, CAP_KEYBOARD, CAP_POINTER, CAP_SWITCH, CAP_TABLET_PAD,
|
||||||
CAP_TABLET_TOOL, CAP_TOUCH,
|
CAP_TABLET_TOOL, CAP_TOUCH,
|
||||||
},
|
},
|
||||||
InputDevice, Seat,
|
FocusFollowsMouseMode, InputDevice, Seat,
|
||||||
},
|
},
|
||||||
keyboard::{mods::Modifiers, syms::KeySym, Keymap},
|
keyboard::{mods::Modifiers, syms::KeySym, Keymap},
|
||||||
logging::LogLevel,
|
logging::LogLevel,
|
||||||
|
|
@ -324,6 +324,20 @@ impl ConfigProxyHandler {
|
||||||
Ok(())
|
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) {
|
fn handle_set_status(&self, status: &str) {
|
||||||
self.state.set_status(status);
|
self.state.set_status(status);
|
||||||
}
|
}
|
||||||
|
|
@ -1791,6 +1805,9 @@ impl ConfigProxyHandler {
|
||||||
} => self
|
} => self
|
||||||
.handle_add_shortcut(seat, mod_mask, mods, sym)
|
.handle_add_shortcut(seat, mod_mask, mods, sym)
|
||||||
.wrn("add_shortcut")?,
|
.wrn("add_shortcut")?,
|
||||||
|
ClientMessage::SetFocusFollowsMouseMode { seat, mode } => self
|
||||||
|
.handle_set_focus_follows_mouse_mode(seat, mode)
|
||||||
|
.wrn("set_focus_follows_mouse_mode")?,
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,7 @@ pub struct WlSeatGlobal {
|
||||||
input_method: CloneCell<Option<Rc<ZwpInputMethodV2>>>,
|
input_method: CloneCell<Option<Rc<ZwpInputMethodV2>>>,
|
||||||
input_method_grab: CloneCell<Option<Rc<ZwpInputMethodKeyboardGrabV2>>>,
|
input_method_grab: CloneCell<Option<Rc<ZwpInputMethodKeyboardGrabV2>>>,
|
||||||
forward: Cell<bool>,
|
forward: Cell<bool>,
|
||||||
|
focus_follows_mouse: Cell<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const CHANGE_CURSOR_MOVED: u32 = 1 << 0;
|
const CHANGE_CURSOR_MOVED: u32 = 1 << 0;
|
||||||
|
|
@ -250,6 +251,7 @@ impl WlSeatGlobal {
|
||||||
input_method: Default::default(),
|
input_method: Default::default(),
|
||||||
input_method_grab: Default::default(),
|
input_method_grab: Default::default(),
|
||||||
forward: Cell::new(false),
|
forward: Cell::new(false),
|
||||||
|
focus_follows_mouse: Cell::new(true),
|
||||||
});
|
});
|
||||||
state.add_cursor_size(*DEFAULT_CURSOR_SIZE);
|
state.add_cursor_size(*DEFAULT_CURSOR_SIZE);
|
||||||
let seat = slf.clone();
|
let seat = slf.clone();
|
||||||
|
|
@ -1165,6 +1167,10 @@ impl WlSeatGlobal {
|
||||||
pub fn select_workspace(self: &Rc<Self>, selector: impl WorkspaceSelector) {
|
pub fn select_workspace(self: &Rc<Self>, selector: impl WorkspaceSelector) {
|
||||||
self.pointer_owner.select_workspace(self, selector);
|
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);
|
global_base!(WlSeatGlobal, WlSeat, WlSeatError);
|
||||||
|
|
|
||||||
|
|
@ -756,7 +756,10 @@ impl WlSeatGlobal {
|
||||||
// Enter callbacks
|
// Enter callbacks
|
||||||
impl WlSeatGlobal {
|
impl WlSeatGlobal {
|
||||||
pub fn enter_toplevel(self: &Rc<Self>, n: Rc<dyn ToplevelNode>) {
|
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);
|
self.focus_toplevel(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -312,6 +312,7 @@ pub struct Config {
|
||||||
pub inputs: Vec<Input>,
|
pub inputs: Vec<Input>,
|
||||||
pub idle: Option<Duration>,
|
pub idle: Option<Duration>,
|
||||||
pub explicit_sync_enabled: Option<bool>,
|
pub explicit_sync_enabled: Option<bool>,
|
||||||
|
pub focus_follows_mouse: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ impl Parser for ConfigParser<'_> {
|
||||||
_,
|
_,
|
||||||
idle_val,
|
idle_val,
|
||||||
),
|
),
|
||||||
(explicit_sync, repeat_rate_val, complex_shortcuts_val),
|
(explicit_sync, repeat_rate_val, complex_shortcuts_val, focus_follows_mouse),
|
||||||
) = ext.extract((
|
) = ext.extract((
|
||||||
(
|
(
|
||||||
opt(val("keymap")),
|
opt(val("keymap")),
|
||||||
|
|
@ -127,6 +127,7 @@ impl Parser for ConfigParser<'_> {
|
||||||
recover(opt(bol("explicit-sync"))),
|
recover(opt(bol("explicit-sync"))),
|
||||||
opt(val("repeat-rate")),
|
opt(val("repeat-rate")),
|
||||||
opt(val("complex-shortcuts")),
|
opt(val("complex-shortcuts")),
|
||||||
|
recover(opt(bol("focus-follows-mouse"))),
|
||||||
),
|
),
|
||||||
))?;
|
))?;
|
||||||
let mut keymap = None;
|
let mut keymap = None;
|
||||||
|
|
@ -307,6 +308,7 @@ impl Parser for ConfigParser<'_> {
|
||||||
render_device,
|
render_device,
|
||||||
inputs,
|
inputs,
|
||||||
idle,
|
idle,
|
||||||
|
focus_follows_mouse: focus_follows_mouse.despan().unwrap_or(true),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,9 @@ use {
|
||||||
config, config_dir,
|
config, config_dir,
|
||||||
exec::{set_env, unset_env, Command},
|
exec::{set_env, unset_env, Command},
|
||||||
get_workspace,
|
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,
|
is_reload,
|
||||||
keyboard::{Keymap, ModifiedKeySym},
|
keyboard::{Keymap, ModifiedKeySym},
|
||||||
logging::set_log_level,
|
logging::set_log_level,
|
||||||
|
|
@ -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 {
|
fn create_command(exec: &Exec) -> Command {
|
||||||
|
|
|
||||||
|
|
@ -569,6 +569,10 @@
|
||||||
"idle": {
|
"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",
|
"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"
|
"$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": []
|
"required": []
|
||||||
|
|
|
||||||
|
|
@ -1086,6 +1086,15 @@ The table has the following fields:
|
||||||
|
|
||||||
The value of this field should be a [Idle](#types-Idle).
|
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>
|
<a name="types-Connector"></a>
|
||||||
### `Connector`
|
### `Connector`
|
||||||
|
|
|
||||||
|
|
@ -2039,6 +2039,14 @@ Config:
|
||||||
```toml
|
```toml
|
||||||
idle.minutes = 10
|
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:
|
Idle:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue