mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2024-12-26 21:58:10 +01:00
Work on focus mechanism
This commit is contained in:
parent
d1bfb48885
commit
3ea2452397
44 changed files with 124 additions and 87 deletions
|
@ -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
|
||||
|
|
|
@ -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.
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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
48
src/focus.rs
Normal 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,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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(
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use smithay::{
|
||||
desktop::{Space, Window},
|
||||
desktop::Window,
|
||||
input::{
|
||||
pointer::{AxisFrame, ButtonEvent, GrabStartData, PointerGrab, PointerInnerHandle},
|
||||
SeatHandler,
|
||||
|
|
|
@ -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>);
|
||||
|
|
16
src/input.rs
16
src/input.rs
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
mod api;
|
||||
mod backend;
|
||||
mod cursor;
|
||||
mod focus;
|
||||
mod grab;
|
||||
mod handlers;
|
||||
mod input;
|
||||
|
|
75
src/state.rs
75
src/state.rs
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue