Work on focus mechanism

This commit is contained in:
Seaotatop 2023-06-17 21:02:58 -05:00
parent d1bfb48885
commit 3ea2452397
44 changed files with 124 additions and 87 deletions

View file

@ -4,10 +4,8 @@ local M = {}
---@param client_id integer? The id of the window you want closed, or nil to close the currently focused window, if any.
function M.close_window(client_id)
SendMsg({
Action = {
CloseWindow = {
client_id = client_id or "nil",
},
CloseWindow = {
client_id = client_id or "nil",
},
})
end

View file

@ -83,7 +83,6 @@ while true do
assert(msg_bytes)
local tb = msgpack.decode(msg_bytes)
print(tb)
if tb.CallCallback then
CallbackTable[tb.CallCallback]()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -2,7 +2,7 @@ pub mod msg;
use std::{
io::{self, Read, Write},
os::unix::net::{UnixDatagram, UnixListener, UnixStream},
os::unix::net::{UnixListener, UnixStream},
path::Path,
};

View file

@ -11,12 +11,9 @@ pub enum Msg {
SetMousebind {
button: u8,
},
// Action(Action),
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub enum Action {
CloseWindow { client_id: Option<u32> },
CloseWindow {
client_id: Option<u32>,
},
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
@ -42,7 +39,7 @@ impl<T: IntoIterator<Item = Modifiers>> From<T> for ModifierMask {
}
}
/// Messages sent from the server to each client.
/// Messages sent from the server to the client.
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub enum OutgoingMsg {
CallCallback(u32),

View file

@ -1,8 +1,4 @@
use smithay::{
backend::input::{InputBackend, InputEvent},
output::Output,
reexports::wayland_server::protocol::wl_surface::WlSurface,
};
use smithay::{output::Output, reexports::wayland_server::protocol::wl_surface::WlSurface};
pub mod udev;
pub mod winit;

View file

@ -3,7 +3,7 @@ use std::{
error::Error,
os::fd::FromRawFd,
path::Path,
sync::{atomic::Ordering, Mutex},
sync::Mutex,
time::Duration,
};
@ -67,9 +67,7 @@ use smithay::{
presentation_time::server::wp_presentation_feedback,
},
wayland_server::{
backend::GlobalId,
protocol::wl_surface::{self, WlSurface},
Display, DisplayHandle,
backend::GlobalId, protocol::wl_surface::WlSurface, Display, DisplayHandle,
},
},
utils::{Clock, DeviceFd, IsAlive, Logical, Monotonic, Point, Scale, Transform},

48
src/focus.rs Normal file
View file

@ -0,0 +1,48 @@
use smithay::{
desktop::Window,
utils::{IsAlive, Serial},
};
use crate::{backend::Backend, state::State};
#[derive(Default)]
pub struct FocusState {
focus_stack: Vec<Window>,
}
impl FocusState {
pub fn new() -> Self {
Default::default()
}
pub fn current_focus(&mut self) -> Option<Window> {
while let Some(window) = self.focus_stack.last() {
if window.alive() {
return Some(window.clone());
}
self.focus_stack.pop();
}
None
}
pub fn set_focus(&mut self, window: Window) {
self.focus_stack.retain(|win| win != &window);
self.focus_stack.push(window);
}
}
impl<B: Backend> State<B> {
pub fn set_focus(&mut self, window: Window, serial: Serial) {
// INFO: this is inserted into the loop because foot didn't like it when you set the focus
// |` immediately after creating the toplevel
// TODO: figure out why
self.loop_handle.insert_idle(move |data| {
data.state.focus_state.set_focus(window.clone());
data.state.seat.get_keyboard().unwrap().set_focus(
&mut data.state,
Some(window.toplevel().wl_surface().clone()),
serial,
);
});
}
}

View file

@ -40,6 +40,7 @@ impl<B: Backend> PointerGrab<State<B>> for MoveSurfaceGrab<State<B>> {
let new_loc = self.initial_window_loc.to_f64() + delta;
data.space
.map_element(self.window.clone(), new_loc.to_i32_round(), true);
data.focus_state.set_focus(self.window.clone());
}
fn relative_motion(

View file

@ -1,5 +1,5 @@
use smithay::{
desktop::{Space, Window},
desktop::Window,
input::{
pointer::{AxisFrame, ButtonEvent, GrabStartData, PointerGrab, PointerInnerHandle},
SeatHandler,

View file

@ -4,8 +4,8 @@ use smithay::{
delegate_presentation, delegate_relative_pointer, delegate_seat, delegate_shm,
delegate_viewporter, delegate_xdg_shell,
desktop::{
find_popup_root_surface, PopupKeyboardGrab, PopupKind, PopupManager, PopupPointerGrab,
PopupUngrabStrategy, Space, Window,
find_popup_root_surface, PopupKeyboardGrab, PopupKind, PopupPointerGrab,
PopupUngrabStrategy, Window,
},
input::{
pointer::{CursorImageStatus, Focus},
@ -19,7 +19,7 @@ use smithay::{
Client, Resource,
},
},
utils::Serial,
utils::{Serial, SERIAL_COUNTER},
wayland::{
buffer::BufferHandler,
compositor::{
@ -32,8 +32,8 @@ use smithay::{
dmabuf,
fractional_scale::{self, FractionalScaleHandler},
shell::xdg::{
Configure, PopupSurface, PositionerState, ToplevelSurface, XdgPopupSurfaceData,
XdgShellHandler, XdgShellState, XdgToplevelSurfaceData,
PopupSurface, PositionerState, ToplevelSurface, XdgPopupSurfaceData, XdgShellHandler,
XdgShellState, XdgToplevelSurfaceData,
},
shm::{ShmHandler, ShmState},
},
@ -112,6 +112,7 @@ impl<B: Backend> CompositorHandler for State<B> {
}
}
delegate_compositor!(@<B: Backend> State<B>);
fn ensure_initial_configure<B: Backend>(surface: &WlSurface, state: &mut State<B>) {
if let Some(window) = state.window_for_surface(surface) {
let initial_configure_sent = compositor::with_states(surface, |states| {
@ -194,15 +195,25 @@ impl<B: Backend> XdgShellHandler for State<B> {
fn new_toplevel(&mut self, surface: ToplevelSurface) {
let window = Window::new(surface);
self.space.map_element(window, (0, 0), true);
self.space.map_element(window.clone(), (0, 0), true);
self.set_focus(window, SERIAL_COUNTER.next_serial());
let windows: Vec<Window> = self.space.elements().cloned().collect();
Layout::master_stack(self, windows, crate::layout::Direction::Left);
}
fn toplevel_destroyed(&mut self, surface: ToplevelSurface) {
let windows: Vec<Window> = self.space.elements().cloned().collect();
let mut windows: Vec<Window> = self.space.elements().cloned().collect();
windows.retain(|window| window.toplevel() != &surface);
Layout::master_stack(self, windows, crate::layout::Direction::Left);
let focus = self
.focus_state
.current_focus()
.map(|win| win.toplevel().wl_surface().clone());
self.seat
.get_keyboard()
.unwrap()
.set_focus(self, focus, SERIAL_COUNTER.next_serial());
}
fn new_popup(&mut self, surface: PopupSurface, positioner: PositionerState) {
@ -291,10 +302,6 @@ impl<B: Backend> XdgShellHandler for State<B> {
}
}
fn ack_configure(&mut self, surface: WlSurface, configure: Configure) {
// println!("surface ack_configure: {:?}", configure);
}
// TODO: impl the rest of the fns in XdgShellHandler
}
delegate_xdg_shell!(@<B: Backend> State<B>);

View file

@ -9,7 +9,7 @@ use smithay::{
desktop::{Window, WindowSurfaceType},
input::{
keyboard::{keysyms, FilterResult},
pointer::{AxisFrame, ButtonEvent, MotionEvent, RelativeMotionEvent},
pointer::{AxisFrame, ButtonEvent, MotionEvent},
},
reexports::wayland_protocols::xdg::shell::server::xdg_toplevel::ResizeEdge,
utils::{Logical, Point, SERIAL_COUNTER},
@ -21,8 +21,18 @@ use crate::{
state::State,
};
#[derive(Default)]
pub struct InputState {
/// A hashmap of modifier keys and keycodes to callback IDs
pub keybinds: HashMap<(ModifierMask, u32), u32>,
/// A hashmap of modifier keys and mouse button codes to callback IDs
pub mousebinds: HashMap<(ModifierMask, u32), u32>,
}
impl InputState {
pub fn new() -> Self {
Default::default()
}
}
impl<B: Backend> State<B> {
@ -121,8 +131,8 @@ impl<B: Backend> State<B> {
// Move window to top of stack.
self.space.raise_element(&window, true);
// Focus on window.
keyboard.set_focus(self, Some(window.toplevel().wl_surface().clone()), serial);
self.set_focus(window, serial);
self.space.elements().for_each(|window| {
window.toplevel().send_configure();
});

View file

@ -1,9 +1,3 @@
use std::{error::Error, fmt::Display};
use smithay::desktop::Window;
use crate::{backend::Backend, state::State};
pub mod automatic;
pub mod manual;

View file

@ -73,6 +73,7 @@ impl Layout {
// INFO: We send configures when the event loop is idle so
// | CompositorHandler::commit() sends the initial configure
// TODO: maybe check if the initial configure was sent instead?
state.loop_handle.insert_idle(|_calloop_data| {
for win in windows {
win.toplevel().send_pending_configure();

View file

@ -1,6 +1,7 @@
mod api;
mod backend;
mod cursor;
mod focus;
mod grab;
mod handlers;
mod input;

View file

@ -1,11 +1,13 @@
use std::{
collections::HashMap,
error::Error,
os::{fd::AsRawFd, unix::net::UnixStream},
sync::Arc,
};
use crate::api::{msg::Msg, PinnacleSocketSource};
use crate::{
api::{msg::Msg, PinnacleSocketSource},
focus::FocusState,
};
use smithay::{
backend::renderer::element::RenderElementStates,
desktop::{
@ -28,7 +30,7 @@ use smithay::{
Display,
},
},
utils::{Clock, Logical, Monotonic, Point},
utils::{Clock, IsAlive, Logical, Monotonic, Point},
wayland::{
compositor::{CompositorClientState, CompositorState},
data_device::DataDeviceState,
@ -68,6 +70,7 @@ pub struct State<B: Backend> {
pub fractional_scale_manager_state: FractionalScaleManagerState,
pub input_state: InputState,
pub api_state: ApiState,
pub focus_state: FocusState,
pub popup_manager: PopupManager,
@ -122,41 +125,31 @@ impl<B: Backend> State<B> {
.insert((modifiers.into(), key), callback_id);
}
Msg::SetMousebind { button } => todo!(),
Msg::CloseWindow { client_id } => {
tracing::info!("CloseWindow {:?}", client_id);
if let Some(window) = data
.state
.seat
.get_keyboard()
.unwrap()
.current_focus()
.and_then(|wl_surface| data.state.window_for_surface(&wl_surface))
{
window.toplevel().send_close();
}
}
};
}
Event::Closed => todo!(),
})?;
// std::thread::spawn(move || {
// crate::api::init_api_socket(tx_channel).unwrap();
// });
// We want to replace the client id a new one pops up
// INFO: this source try_clone()s the stream
loop_handle.insert_source(PinnacleSocketSource::new(tx_channel)?, |stream, _, data| {
if let Some(old_stream) = data.state.api_state.stream.replace(stream) {
old_stream.shutdown(std::net::Shutdown::Both).unwrap();
}
})?;
// data.state
// .loop_handle
// .insert_source(PinnacleStreamSource::new(stream), |msg, _, data| {
// // TODO: do stuff with msg
// match msg {
// Msg::SetKeybind {
// key,
// modifiers,
// callback_id,
// } => {
// tracing::info!("set keybind: {:?}, {}", modifiers, key);
// data.state
// .input_state
// .keybinds
// .insert((modifiers.into(), key), callback_id);
// }
// Msg::SetMousebind { button } => todo!(),
// };
// })
// .unwrap();
// })?;
let display_handle = display.handle();
let mut seat_state = SeatState::new();
@ -182,10 +175,9 @@ impl<B: Backend> State<B> {
fractional_scale_manager_state: FractionalScaleManagerState::new::<Self>(
&display_handle,
),
input_state: InputState {
keybinds: HashMap::new(),
},
api_state: ApiState { stream: None },
input_state: InputState::new(),
api_state: ApiState::new(),
focus_state: FocusState::new(),
seat,
@ -203,18 +195,6 @@ impl<B: Backend> State<B> {
.find(|window| window.wl_surface().map(|s| s == *surface).unwrap_or(false))
.cloned()
}
// TODO:
pub fn handle_msg(msg: Msg) {
match msg {
Msg::SetKeybind {
key,
modifiers,
callback_id,
} => todo!(),
Msg::SetMousebind { button } => todo!(),
}
}
}
pub struct CalloopData<B: Backend> {
@ -272,6 +252,13 @@ pub fn take_presentation_feedback(
output_presentation_feedback
}
#[derive(Default)]
pub struct ApiState {
pub stream: Option<UnixStream>,
}
impl ApiState {
pub fn new() -> Self {
Default::default()
}
}