added cursor_follows_focus and focus_follows_cursor
This commit is contained in:
parent
52280e9823
commit
7da0bc430a
22 changed files with 844 additions and 384 deletions
|
|
@ -27,6 +27,10 @@ use super::grabs::{SeatMenuGrabState, SeatMoveGrabState};
|
|||
|
||||
crate::utils::id_gen!(next_seat_id, SEAT_ID, SEAT_IDS);
|
||||
|
||||
// for more information on seats, see:
|
||||
// <https://wayland-book.com/print.html#seats-handling-input>
|
||||
/// Seats are an abstraction over a set of input devices grouped together, such as a keyboard, pointer and touch device.
|
||||
/// i.e. Those used by a user to operate the computer.
|
||||
#[derive(Debug)]
|
||||
pub struct Seats {
|
||||
seats: Vec<Seat<State>>,
|
||||
|
|
@ -155,8 +159,13 @@ impl Drop for SeatId {
|
|||
|
||||
#[repr(transparent)]
|
||||
struct SeatId(pub usize);
|
||||
|
||||
/// The output which contains the cursor associated with a seat.
|
||||
struct ActiveOutput(pub Mutex<Output>);
|
||||
|
||||
/// The output which currently has keyboard focus
|
||||
struct FocusedOutput(pub Mutex<Option<Output>>);
|
||||
|
||||
pub fn create_seat(
|
||||
dh: &DisplayHandle,
|
||||
seat_state: &mut SeatState<State>,
|
||||
|
|
@ -175,6 +184,7 @@ pub fn create_seat(
|
|||
userdata.insert_if_missing_threadsafe(SeatMenuGrabState::default);
|
||||
userdata.insert_if_missing_threadsafe(CursorState::default);
|
||||
userdata.insert_if_missing_threadsafe(|| ActiveOutput(Mutex::new(output.clone())));
|
||||
userdata.insert_if_missing_threadsafe(|| FocusedOutput(Mutex::new(None)));
|
||||
userdata.insert_if_missing_threadsafe(|| Mutex::new(CursorImageStatus::default_named()));
|
||||
|
||||
// A lot of clients bind keyboard and pointer unconditionally once on launch..
|
||||
|
|
@ -213,7 +223,13 @@ pub trait SeatExt {
|
|||
fn id(&self) -> usize;
|
||||
|
||||
fn active_output(&self) -> Output;
|
||||
fn focused_output(&self) -> Option<Output>;
|
||||
fn focused_or_active_output(&self) -> Output {
|
||||
self.focused_output()
|
||||
.unwrap_or_else(|| self.active_output())
|
||||
}
|
||||
fn set_active_output(&self, output: &Output);
|
||||
fn set_focused_output(&self, output: Option<&Output>);
|
||||
fn devices(&self) -> &Devices;
|
||||
fn supressed_keys(&self) -> &SupressedKeys;
|
||||
fn supressed_buttons(&self) -> &SupressedButtons;
|
||||
|
|
@ -231,6 +247,9 @@ impl SeatExt for Seat<State> {
|
|||
self.user_data().get::<SeatId>().unwrap().0
|
||||
}
|
||||
|
||||
/// Returns the output that contains the cursor associated with a seat. Note that the window which has keyboard focus
|
||||
/// may be on a different output. Currently, to get the focused output, first get the keyboard focus target and pass
|
||||
/// it to get_focused_output in the shell.
|
||||
fn active_output(&self) -> Output {
|
||||
self.user_data()
|
||||
.get::<ActiveOutput>()
|
||||
|
|
@ -238,6 +257,21 @@ impl SeatExt for Seat<State> {
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
/// Returns the output which currently has keyboard focus. If no window has keyboard focus (e.g. when there are no windows)
|
||||
/// the focused output will be the same as the active output.
|
||||
fn focused_output(&self) -> Option<Output> {
|
||||
if self
|
||||
.get_keyboard()
|
||||
.is_some_and(|k| k.current_focus().is_some())
|
||||
{
|
||||
self.user_data()
|
||||
.get::<FocusedOutput>()
|
||||
.map(|x| x.0.lock().unwrap().clone())?
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn set_active_output(&self, output: &Output) {
|
||||
*self
|
||||
.user_data()
|
||||
|
|
@ -248,6 +282,16 @@ impl SeatExt for Seat<State> {
|
|||
.unwrap() = output.clone();
|
||||
}
|
||||
|
||||
fn set_focused_output(&self, output: Option<&Output>) {
|
||||
*self
|
||||
.user_data()
|
||||
.get::<FocusedOutput>()
|
||||
.unwrap()
|
||||
.0
|
||||
.lock()
|
||||
.unwrap() = output.cloned();
|
||||
}
|
||||
|
||||
fn devices(&self) -> &Devices {
|
||||
self.user_data().get::<Devices>().unwrap()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue