config: add mouse-follows-focus option
This commit is contained in:
parent
0d4ee299d4
commit
216d104b73
14 changed files with 134 additions and 6 deletions
|
|
@ -2425,6 +2425,16 @@ impl ConfigProxyHandler {
|
|||
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> {
|
||||
use jay_config::theme::sized::*;
|
||||
let sized = match sized {
|
||||
|
|
@ -2597,6 +2607,7 @@ impl ConfigProxyHandler {
|
|||
return Err(CphError::WindowNotVisible(window_id));
|
||||
}
|
||||
seat.focus_toplevel(window);
|
||||
seat.maybe_schedule_warp_mouse_to_focus();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -3354,6 +3365,9 @@ impl ConfigProxyHandler {
|
|||
ClientMessage::SeatWarpMouseToFocus { seat } => self
|
||||
.handle_seat_warp_mouse_to_focus(seat)
|
||||
.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 {
|
||||
connector,
|
||||
use_native_gamut,
|
||||
|
|
|
|||
|
|
@ -232,6 +232,9 @@ impl InputPane {
|
|||
bool(ui, "Focus Follows Mouse", seat.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(
|
||||
ui,
|
||||
"Fallback Output Mode",
|
||||
|
|
|
|||
|
|
@ -260,6 +260,8 @@ pub struct WlSeatGlobal {
|
|||
simple_im: CloneCell<Option<Rc<SimpleIm>>>,
|
||||
simple_im_enabled: 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 {
|
||||
|
|
@ -403,6 +405,8 @@ impl WlSeatGlobal {
|
|||
simple_im: CloneCell::new(simple_im),
|
||||
simple_im_enabled: Cell::new(true),
|
||||
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.modifiers_listener
|
||||
|
|
@ -537,12 +541,13 @@ impl WlSeatGlobal {
|
|||
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() {
|
||||
Some(tl) => tl,
|
||||
_ => return,
|
||||
};
|
||||
toplevel_set_workspace(&self.state, tl, ws);
|
||||
self.maybe_schedule_warp_mouse_to_focus();
|
||||
}
|
||||
|
||||
pub fn mark_last_active(self: &Rc<Self>) {
|
||||
|
|
@ -743,6 +748,7 @@ impl WlSeatGlobal {
|
|||
&& let Some(tl) = parent.node_toplevel()
|
||||
{
|
||||
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)
|
||||
{
|
||||
target.take_keyboard_navigation_focus(self, direction);
|
||||
self.maybe_schedule_warp_mouse_to_focus();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -821,6 +828,14 @@ impl WlSeatGlobal {
|
|||
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>) {
|
||||
|
|
@ -848,10 +863,12 @@ impl WlSeatGlobal {
|
|||
{
|
||||
let ws = target.ensure_workspace();
|
||||
toplevel_set_workspace(&self.state, tl, &ws);
|
||||
self.maybe_schedule_warp_mouse_to_focus();
|
||||
} else if let Some(parent) = data.parent.get()
|
||||
&& let Some(c) = parent.node_into_container()
|
||||
{
|
||||
c.move_child(tl, direction);
|
||||
self.maybe_schedule_warp_mouse_to_focus();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -972,6 +989,7 @@ impl WlSeatGlobal {
|
|||
}
|
||||
}
|
||||
self.focus_node(node);
|
||||
self.maybe_schedule_warp_mouse_to_focus();
|
||||
}
|
||||
|
||||
pub fn focus_prev(self: &Rc<Self>) {
|
||||
|
|
@ -1035,6 +1053,7 @@ impl WlSeatGlobal {
|
|||
n.deref()
|
||||
.clone()
|
||||
.node_do_focus(self, Direction::Unspecified);
|
||||
self.maybe_schedule_warp_mouse_to_focus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1046,6 +1065,7 @@ impl WlSeatGlobal {
|
|||
n.deref()
|
||||
.clone()
|
||||
.node_do_focus(self, Direction::Unspecified);
|
||||
self.maybe_schedule_warp_mouse_to_focus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1087,6 +1107,7 @@ impl WlSeatGlobal {
|
|||
&& ws.container_visible()
|
||||
{
|
||||
self.focus_node(ws.clone());
|
||||
self.maybe_schedule_warp_mouse_to_focus();
|
||||
return;
|
||||
}
|
||||
None
|
||||
|
|
@ -1111,6 +1132,7 @@ impl WlSeatGlobal {
|
|||
if let Some(n) = node {
|
||||
if node_viable(&*n) {
|
||||
n.node_do_focus(self, Direction::Unspecified);
|
||||
self.maybe_schedule_warp_mouse_to_focus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1164,6 +1186,7 @@ impl WlSeatGlobal {
|
|||
};
|
||||
if node.node_visible() && node.node_accepts_focus() {
|
||||
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()
|
||||
}
|
||||
|
||||
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) {
|
||||
self.fallback_output_mode.set(fallback_output_mode);
|
||||
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;
|
||||
while let Some(seat) = state.pending_warp_mouse_to_focus.try_pop() {
|
||||
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 {
|
||||
continue;
|
||||
};
|
||||
let (x, y) = tl.node_absolute_position().center();
|
||||
let Some(target) = state.node_at(x, y).node.node_toplevel() else {
|
||||
continue;
|
||||
};
|
||||
if target.node_id() != tl.node_id() {
|
||||
continue;
|
||||
if !skip_target_check {
|
||||
let Some(target) = state.node_at(x, y).node.node_toplevel() else {
|
||||
continue;
|
||||
};
|
||||
if target.node_id() != tl.node_id() {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let (x, y) = (Fixed::from_int(x), Fixed::from_int(y));
|
||||
seat.motion_event_abs(state.now_usec(), x, y, Warp);
|
||||
|
|
|
|||
|
|
@ -1084,6 +1084,7 @@ impl WlSeatGlobal {
|
|||
}
|
||||
}
|
||||
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);
|
||||
seat.maybe_schedule_warp_mouse_to_focus();
|
||||
}
|
||||
|
||||
pub fn float_map_ws(&self) -> Rc<WorkspaceNode> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue