Merge pull request #785 from Ktrompfl/warp-cursor-on-move-focus
Add mouse-refocus option to center cursor on focused window
This commit is contained in:
commit
4955c8d248
14 changed files with 134 additions and 6 deletions
|
|
@ -1108,6 +1108,10 @@ impl ConfigClient {
|
||||||
self.send(&ClientMessage::SeatEnableUnicodeInput { seat });
|
self.send(&ClientMessage::SeatEnableUnicodeInput { seat });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn seat_set_mouse_follows_focus(&self, seat: Seat, enabled: bool) {
|
||||||
|
self.send(&ClientMessage::SeatSetMouseFollowsFocus { seat, enabled });
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_show_float_pin_icon(&self, show: bool) {
|
pub fn set_show_float_pin_icon(&self, show: bool) {
|
||||||
self.send(&ClientMessage::SetShowFloatPinIcon { show });
|
self.send(&ClientMessage::SetShowFloatPinIcon { show });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -871,6 +871,10 @@ pub enum ClientMessage<'a> {
|
||||||
dx2: i32,
|
dx2: i32,
|
||||||
dy2: i32,
|
dy2: i32,
|
||||||
},
|
},
|
||||||
|
SeatSetMouseFollowsFocus {
|
||||||
|
seat: Seat,
|
||||||
|
enabled: bool,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
|
|
||||||
|
|
@ -655,6 +655,15 @@ impl Seat {
|
||||||
pub fn resize(self, dx1: i32, dy1: i32, dx2: i32, dy2: i32) {
|
pub fn resize(self, dx1: i32, dy1: i32, dx2: i32, dy2: i32) {
|
||||||
self.window().resize(dx1, dy1, dx2, dy2);
|
self.window().resize(dx1, dy1, dx2, dy2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets whether the cursor should automatically move to the center of a window
|
||||||
|
/// when focus changes via keyboard commands (move-left, focus-right, show-workspace, etc.).
|
||||||
|
///
|
||||||
|
/// The default is `false`.
|
||||||
|
#[deprecated = "This setting is unstable and might be removed in the future"]
|
||||||
|
pub fn unstable_set_mouse_follows_focus(self, enabled: bool) {
|
||||||
|
get!().seat_set_mouse_follows_focus(self, enabled)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A focus-follows-mouse mode.
|
/// A focus-follows-mouse mode.
|
||||||
|
|
|
||||||
|
|
@ -2425,6 +2425,16 @@ impl ConfigProxyHandler {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_seat_set_mouse_follows_focus(
|
||||||
|
&self,
|
||||||
|
seat: Seat,
|
||||||
|
enabled: bool,
|
||||||
|
) -> Result<(), CphError> {
|
||||||
|
let seat = self.get_seat(seat)?;
|
||||||
|
seat.set_mouse_follows_focus(enabled);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn get_sized(&self, sized: Resizable) -> Result<ThemeSized, CphError> {
|
fn get_sized(&self, sized: Resizable) -> Result<ThemeSized, CphError> {
|
||||||
use jay_config::theme::sized::*;
|
use jay_config::theme::sized::*;
|
||||||
let sized = match sized {
|
let sized = match sized {
|
||||||
|
|
@ -2597,6 +2607,7 @@ impl ConfigProxyHandler {
|
||||||
return Err(CphError::WindowNotVisible(window_id));
|
return Err(CphError::WindowNotVisible(window_id));
|
||||||
}
|
}
|
||||||
seat.focus_toplevel(window);
|
seat.focus_toplevel(window);
|
||||||
|
seat.maybe_schedule_warp_mouse_to_focus();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3354,6 +3365,9 @@ impl ConfigProxyHandler {
|
||||||
ClientMessage::SeatWarpMouseToFocus { seat } => self
|
ClientMessage::SeatWarpMouseToFocus { seat } => self
|
||||||
.handle_seat_warp_mouse_to_focus(seat)
|
.handle_seat_warp_mouse_to_focus(seat)
|
||||||
.wrn("seat_warp_mouse_to_focus")?,
|
.wrn("seat_warp_mouse_to_focus")?,
|
||||||
|
ClientMessage::SeatSetMouseFollowsFocus { seat, enabled } => self
|
||||||
|
.handle_seat_set_mouse_follows_focus(seat, enabled)
|
||||||
|
.wrn("seat_set_mouse_follows_focus")?,
|
||||||
ClientMessage::ConnectorSetUseNativeGamut {
|
ClientMessage::ConnectorSetUseNativeGamut {
|
||||||
connector,
|
connector,
|
||||||
use_native_gamut,
|
use_native_gamut,
|
||||||
|
|
|
||||||
|
|
@ -232,6 +232,9 @@ impl InputPane {
|
||||||
bool(ui, "Focus Follows Mouse", seat.focus_follows_mouse(), |v| {
|
bool(ui, "Focus Follows Mouse", seat.focus_follows_mouse(), |v| {
|
||||||
seat.set_focus_follows_mouse(v);
|
seat.set_focus_follows_mouse(v);
|
||||||
});
|
});
|
||||||
|
bool(ui, "Mouse Follows Focus", seat.mouse_follows_focus(), |v| {
|
||||||
|
seat.set_mouse_follows_focus(v);
|
||||||
|
});
|
||||||
combo_box_ui(
|
combo_box_ui(
|
||||||
ui,
|
ui,
|
||||||
"Fallback Output Mode",
|
"Fallback Output Mode",
|
||||||
|
|
|
||||||
|
|
@ -260,6 +260,8 @@ pub struct WlSeatGlobal {
|
||||||
simple_im: CloneCell<Option<Rc<SimpleIm>>>,
|
simple_im: CloneCell<Option<Rc<SimpleIm>>>,
|
||||||
simple_im_enabled: Cell<bool>,
|
simple_im_enabled: Cell<bool>,
|
||||||
warp_mouse_to_focus_scheduled: Cell<bool>,
|
warp_mouse_to_focus_scheduled: Cell<bool>,
|
||||||
|
warp_mouse_to_focus_skip_target_check: Cell<bool>,
|
||||||
|
mouse_follows_focus: Cell<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for WlSeatGlobal {
|
impl PartialEq for WlSeatGlobal {
|
||||||
|
|
@ -403,6 +405,8 @@ impl WlSeatGlobal {
|
||||||
simple_im: CloneCell::new(simple_im),
|
simple_im: CloneCell::new(simple_im),
|
||||||
simple_im_enabled: Cell::new(true),
|
simple_im_enabled: Cell::new(true),
|
||||||
warp_mouse_to_focus_scheduled: Cell::new(false),
|
warp_mouse_to_focus_scheduled: Cell::new(false),
|
||||||
|
warp_mouse_to_focus_skip_target_check: Cell::new(false),
|
||||||
|
mouse_follows_focus: Cell::new(false),
|
||||||
});
|
});
|
||||||
slf.pointer_cursor.set_owner(slf.clone());
|
slf.pointer_cursor.set_owner(slf.clone());
|
||||||
slf.modifiers_listener
|
slf.modifiers_listener
|
||||||
|
|
@ -537,12 +541,13 @@ impl WlSeatGlobal {
|
||||||
self.get_cursor_output()
|
self.get_cursor_output()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_workspace(&self, ws: &Rc<WorkspaceNode>) {
|
pub fn set_workspace(self: &Rc<Self>, ws: &Rc<WorkspaceNode>) {
|
||||||
let tl = match self.keyboard_node.get().node_toplevel() {
|
let tl = match self.keyboard_node.get().node_toplevel() {
|
||||||
Some(tl) => tl,
|
Some(tl) => tl,
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
toplevel_set_workspace(&self.state, tl, ws);
|
toplevel_set_workspace(&self.state, tl, ws);
|
||||||
|
self.maybe_schedule_warp_mouse_to_focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mark_last_active(self: &Rc<Self>) {
|
pub fn mark_last_active(self: &Rc<Self>) {
|
||||||
|
|
@ -743,6 +748,7 @@ impl WlSeatGlobal {
|
||||||
&& let Some(tl) = parent.node_toplevel()
|
&& let Some(tl) = parent.node_toplevel()
|
||||||
{
|
{
|
||||||
self.focus_node(tl);
|
self.focus_node(tl);
|
||||||
|
self.maybe_schedule_warp_mouse_to_focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -802,6 +808,7 @@ impl WlSeatGlobal {
|
||||||
.find_output_in_direction(&ws.output.get(), direction)
|
.find_output_in_direction(&ws.output.get(), direction)
|
||||||
{
|
{
|
||||||
target.take_keyboard_navigation_focus(self, direction);
|
target.take_keyboard_navigation_focus(self, direction);
|
||||||
|
self.maybe_schedule_warp_mouse_to_focus();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -821,6 +828,14 @@ impl WlSeatGlobal {
|
||||||
c.move_focus_from_child(self, tl.deref(), direction);
|
c.move_focus_from_child(self, tl.deref(), direction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.maybe_schedule_warp_mouse_to_focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn maybe_schedule_warp_mouse_to_focus(self: &Rc<Self>) {
|
||||||
|
if self.mouse_follows_focus() {
|
||||||
|
self.warp_mouse_to_focus_skip_target_check.set(true);
|
||||||
|
self.schedule_warp_mouse_to_focus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn schedule_warp_mouse_to_focus(self: &Rc<Self>) {
|
pub fn schedule_warp_mouse_to_focus(self: &Rc<Self>) {
|
||||||
|
|
@ -848,10 +863,12 @@ impl WlSeatGlobal {
|
||||||
{
|
{
|
||||||
let ws = target.ensure_workspace();
|
let ws = target.ensure_workspace();
|
||||||
toplevel_set_workspace(&self.state, tl, &ws);
|
toplevel_set_workspace(&self.state, tl, &ws);
|
||||||
|
self.maybe_schedule_warp_mouse_to_focus();
|
||||||
} else if let Some(parent) = data.parent.get()
|
} else if let Some(parent) = data.parent.get()
|
||||||
&& let Some(c) = parent.node_into_container()
|
&& let Some(c) = parent.node_into_container()
|
||||||
{
|
{
|
||||||
c.move_child(tl, direction);
|
c.move_child(tl, direction);
|
||||||
|
self.maybe_schedule_warp_mouse_to_focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -972,6 +989,7 @@ impl WlSeatGlobal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.focus_node(node);
|
self.focus_node(node);
|
||||||
|
self.maybe_schedule_warp_mouse_to_focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn focus_prev(self: &Rc<Self>) {
|
pub fn focus_prev(self: &Rc<Self>) {
|
||||||
|
|
@ -1035,6 +1053,7 @@ impl WlSeatGlobal {
|
||||||
n.deref()
|
n.deref()
|
||||||
.clone()
|
.clone()
|
||||||
.node_do_focus(self, Direction::Unspecified);
|
.node_do_focus(self, Direction::Unspecified);
|
||||||
|
self.maybe_schedule_warp_mouse_to_focus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1046,6 +1065,7 @@ impl WlSeatGlobal {
|
||||||
n.deref()
|
n.deref()
|
||||||
.clone()
|
.clone()
|
||||||
.node_do_focus(self, Direction::Unspecified);
|
.node_do_focus(self, Direction::Unspecified);
|
||||||
|
self.maybe_schedule_warp_mouse_to_focus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1087,6 +1107,7 @@ impl WlSeatGlobal {
|
||||||
&& ws.container_visible()
|
&& ws.container_visible()
|
||||||
{
|
{
|
||||||
self.focus_node(ws.clone());
|
self.focus_node(ws.clone());
|
||||||
|
self.maybe_schedule_warp_mouse_to_focus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
|
@ -1111,6 +1132,7 @@ impl WlSeatGlobal {
|
||||||
if let Some(n) = node {
|
if let Some(n) = node {
|
||||||
if node_viable(&*n) {
|
if node_viable(&*n) {
|
||||||
n.node_do_focus(self, Direction::Unspecified);
|
n.node_do_focus(self, Direction::Unspecified);
|
||||||
|
self.maybe_schedule_warp_mouse_to_focus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1164,6 +1186,7 @@ impl WlSeatGlobal {
|
||||||
};
|
};
|
||||||
if node.node_visible() && node.node_accepts_focus() {
|
if node.node_visible() && node.node_accepts_focus() {
|
||||||
node.node_do_focus(self, Direction::Unspecified);
|
node.node_do_focus(self, Direction::Unspecified);
|
||||||
|
self.maybe_schedule_warp_mouse_to_focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1507,6 +1530,15 @@ impl WlSeatGlobal {
|
||||||
self.focus_follows_mouse.get()
|
self.focus_follows_mouse.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_mouse_follows_focus(&self, enabled: bool) {
|
||||||
|
self.mouse_follows_focus.set(enabled);
|
||||||
|
self.state.trigger_cci(CCI_INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mouse_follows_focus(&self) -> bool {
|
||||||
|
self.mouse_follows_focus.get()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_fallback_output_mode(&self, fallback_output_mode: FallbackOutputMode) {
|
pub fn set_fallback_output_mode(&self, fallback_output_mode: FallbackOutputMode) {
|
||||||
self.fallback_output_mode.set(fallback_output_mode);
|
self.fallback_output_mode.set(fallback_output_mode);
|
||||||
self.state.trigger_cci(CCI_INPUT);
|
self.state.trigger_cci(CCI_INPUT);
|
||||||
|
|
@ -2023,15 +2055,18 @@ pub async fn handle_warp_mouse_to_focus(state: Rc<State>) {
|
||||||
state.eng.yield_now().await;
|
state.eng.yield_now().await;
|
||||||
while let Some(seat) = state.pending_warp_mouse_to_focus.try_pop() {
|
while let Some(seat) = state.pending_warp_mouse_to_focus.try_pop() {
|
||||||
seat.warp_mouse_to_focus_scheduled.set(false);
|
seat.warp_mouse_to_focus_scheduled.set(false);
|
||||||
|
let skip_target_check = seat.warp_mouse_to_focus_skip_target_check.take();
|
||||||
let Some(tl) = seat.keyboard_node.get().node_toplevel() else {
|
let Some(tl) = seat.keyboard_node.get().node_toplevel() else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let (x, y) = tl.node_absolute_position().center();
|
let (x, y) = tl.node_absolute_position().center();
|
||||||
let Some(target) = state.node_at(x, y).node.node_toplevel() else {
|
if !skip_target_check {
|
||||||
continue;
|
let Some(target) = state.node_at(x, y).node.node_toplevel() else {
|
||||||
};
|
continue;
|
||||||
if target.node_id() != tl.node_id() {
|
};
|
||||||
continue;
|
if target.node_id() != tl.node_id() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let (x, y) = (Fixed::from_int(x), Fixed::from_int(y));
|
let (x, y) = (Fixed::from_int(x), Fixed::from_int(y));
|
||||||
seat.motion_event_abs(state.now_usec(), x, y, Warp);
|
seat.motion_event_abs(state.now_usec(), x, y, Warp);
|
||||||
|
|
|
||||||
|
|
@ -1084,6 +1084,7 @@ impl WlSeatGlobal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.focus_node(node);
|
self.focus_node(node);
|
||||||
|
self.maybe_schedule_warp_mouse_to_focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -974,6 +974,7 @@ impl State {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.show_workspace2(Some(seat), &ws.output.get(), &ws);
|
self.show_workspace2(Some(seat), &ws.output.get(), &ws);
|
||||||
|
seat.maybe_schedule_warp_mouse_to_focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn float_map_ws(&self) -> Rc<WorkspaceNode> {
|
pub fn float_map_ws(&self) -> Rc<WorkspaceNode> {
|
||||||
|
|
|
||||||
|
|
@ -563,6 +563,7 @@ pub struct Config {
|
||||||
pub workspace_display_order: Option<WorkspaceDisplayOrder>,
|
pub workspace_display_order: Option<WorkspaceDisplayOrder>,
|
||||||
pub simple_im: Option<SimpleIm>,
|
pub simple_im: Option<SimpleIm>,
|
||||||
pub fallback_output_mode: Option<FallbackOutputMode>,
|
pub fallback_output_mode: Option<FallbackOutputMode>,
|
||||||
|
pub mouse_follows_focus: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,7 @@ impl Parser for ConfigParser<'_> {
|
||||||
fallback_output_mode_val,
|
fallback_output_mode_val,
|
||||||
egui_val,
|
egui_val,
|
||||||
clean_logs_older_than_val,
|
clean_logs_older_than_val,
|
||||||
|
mouse_follows_focus,
|
||||||
),
|
),
|
||||||
) = ext.extract((
|
) = ext.extract((
|
||||||
(
|
(
|
||||||
|
|
@ -214,6 +215,7 @@ impl Parser for ConfigParser<'_> {
|
||||||
opt(val("fallback-output-mode")),
|
opt(val("fallback-output-mode")),
|
||||||
opt(val("egui")),
|
opt(val("egui")),
|
||||||
opt(val("clean-logs-older-than")),
|
opt(val("clean-logs-older-than")),
|
||||||
|
recover(opt(bol("unstable-mouse-follows-focus"))),
|
||||||
),
|
),
|
||||||
))?;
|
))?;
|
||||||
let mut keymap = None;
|
let mut keymap = None;
|
||||||
|
|
@ -615,6 +617,7 @@ impl Parser for ConfigParser<'_> {
|
||||||
workspace_display_order,
|
workspace_display_order,
|
||||||
simple_im,
|
simple_im,
|
||||||
fallback_output_mode,
|
fallback_output_mode,
|
||||||
|
mouse_follows_focus: mouse_follows_focus.despan(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1664,6 +1664,12 @@ fn load_config(initial_load: bool, auto_reload: bool, persistent: &Rc<Persistent
|
||||||
if let Some(f) = &config.egui.monospace_fonts {
|
if let Some(f) = &config.egui.monospace_fonts {
|
||||||
set_egui_monospace_fonts(f.iter().map(|s| &**s));
|
set_egui_monospace_fonts(f.iter().map(|s| &**s));
|
||||||
}
|
}
|
||||||
|
if let Some(mouse_follows_focus) = config.mouse_follows_focus {
|
||||||
|
#[expect(deprecated)]
|
||||||
|
persistent
|
||||||
|
.seat
|
||||||
|
.unstable_set_mouse_follows_focus(mouse_follows_focus);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_command(exec: &Exec) -> Command {
|
fn create_command(exec: &Exec) -> Command {
|
||||||
|
|
|
||||||
|
|
@ -1061,6 +1061,10 @@
|
||||||
"type": "boolean",
|
"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"
|
"description": "Configures whether moving the mouse over a window automatically moves the keyboard\nfocus to that window.\n\nThe default is `true`.\n"
|
||||||
},
|
},
|
||||||
|
"unstable-mouse-follows-focus": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Configures whether the mouse cursor is automatically centered on the active window\nwhen focus changes via keyboard commands.\n\nWhen enabled, the cursor will be automatically positioned to the center of the\nactive window when focus changes through keyboard commands such as `focus-left`,\n`focus-right`, `show-workspace`, etc.\n\nThe default is `false`.\n\nThis option is unstable due to various issues. It is not subject to the usual\nsemver guarantees.\n\n- Example:\n\n ```toml\n unstable-mouse-follows-focus = true\n ```\n"
|
||||||
|
},
|
||||||
"window-management-key": {
|
"window-management-key": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Configures a key that will enable window management mode while pressed.\n\nIn window management mode, floating windows can be moved by pressing the left\nmouse button and all windows can be resize by pressing the right mouse button.\n\n- Example:\n\n ```toml\n window-management-key = \"Alt_L\"\n ```\n"
|
"description": "Configures a key that will enable window management mode while pressed.\n\nIn window management mode, floating windows can be moved by pressing the left\nmouse button and all windows can be resize by pressing the right mouse button.\n\n- Example:\n\n ```toml\n window-management-key = \"Alt_L\"\n ```\n"
|
||||||
|
|
|
||||||
|
|
@ -2076,6 +2076,28 @@ The table has the following fields:
|
||||||
|
|
||||||
The value of this field should be a boolean.
|
The value of this field should be a boolean.
|
||||||
|
|
||||||
|
- `unstable-mouse-follows-focus` (optional):
|
||||||
|
|
||||||
|
Configures whether the mouse cursor is automatically centered on the active window
|
||||||
|
when focus changes via keyboard commands.
|
||||||
|
|
||||||
|
When enabled, the cursor will be automatically positioned to the center of the
|
||||||
|
active window when focus changes through keyboard commands such as `focus-left`,
|
||||||
|
`focus-right`, `show-workspace`, etc.
|
||||||
|
|
||||||
|
The default is `false`.
|
||||||
|
|
||||||
|
This option is unstable due to various issues. It is not subject to the usual
|
||||||
|
semver guarantees.
|
||||||
|
|
||||||
|
- Example:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
unstable-mouse-follows-focus = true
|
||||||
|
```
|
||||||
|
|
||||||
|
The value of this field should be a boolean.
|
||||||
|
|
||||||
- `window-management-key` (optional):
|
- `window-management-key` (optional):
|
||||||
|
|
||||||
Configures a key that will enable window management mode while pressed.
|
Configures a key that will enable window management mode while pressed.
|
||||||
|
|
|
||||||
|
|
@ -2865,6 +2865,27 @@ Config:
|
||||||
focus to that window.
|
focus to that window.
|
||||||
|
|
||||||
The default is `true`.
|
The default is `true`.
|
||||||
|
unstable-mouse-follows-focus:
|
||||||
|
kind: boolean
|
||||||
|
required: false
|
||||||
|
description: |
|
||||||
|
Configures whether the mouse cursor is automatically centered on the active window
|
||||||
|
when focus changes via keyboard commands.
|
||||||
|
|
||||||
|
When enabled, the cursor will be automatically positioned to the center of the
|
||||||
|
active window when focus changes through keyboard commands such as `focus-left`,
|
||||||
|
`focus-right`, `show-workspace`, etc.
|
||||||
|
|
||||||
|
The default is `false`.
|
||||||
|
|
||||||
|
This option is unstable due to various issues. It is not subject to the usual
|
||||||
|
semver guarantees.
|
||||||
|
|
||||||
|
- Example:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
unstable-mouse-follows-focus = true
|
||||||
|
```
|
||||||
window-management-key:
|
window-management-key:
|
||||||
kind: string
|
kind: string
|
||||||
required: false
|
required: false
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue