pinnacle/src/window.rs

129 lines
4.1 KiB
Rust
Raw Normal View History

2023-06-25 17:18:50 -05:00
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
2023-06-25 17:49:06 -05:00
//
// SPDX-License-Identifier: MPL-2.0
2023-06-25 17:18:50 -05:00
2023-05-28 19:14:30 -05:00
use std::cell::RefCell;
2023-06-18 19:30:52 -05:00
use smithay::{
desktop::Window,
reexports::wayland_server::protocol::wl_surface::WlSurface,
wayland::{compositor, seat::WaylandFocus},
2023-06-18 19:30:52 -05:00
};
2023-05-28 19:14:30 -05:00
use crate::{backend::Backend, output::OutputState, state::State};
2023-05-28 19:14:30 -05:00
use self::window_state::{Float, WindowId, WindowState};
2023-05-28 19:14:30 -05:00
pub mod window_state;
2023-06-25 20:26:52 -05:00
// TODO: maybe get rid of this and move the fn into resize_surface state because it's the only user
2023-05-28 19:14:30 -05:00
pub trait SurfaceState: Default + 'static {
2023-06-25 20:26:52 -05:00
/// Access the [`SurfaceState`] associated with a [`WlSurface`].
///
/// # Panics
///
2023-06-25 20:26:52 -05:00
/// This function will panic if you use it within itself due to the use of a [`RefCell`].
2023-05-28 19:14:30 -05:00
fn with_state<F, T>(wl_surface: &WlSurface, function: F) -> T
where
F: FnOnce(&mut Self) -> T,
{
compositor::with_states(wl_surface, |states| {
states.data_map.insert_if_missing(RefCell::<Self>::default);
let state = states
.data_map
.get::<RefCell<Self>>()
.expect("This should never happen");
2023-05-28 19:14:30 -05:00
function(&mut state.borrow_mut())
})
}
}
impl<B: Backend> State<B> {
/// Returns the [Window] associated with a given [WlSurface].
pub fn window_for_surface(&self, surface: &WlSurface) -> Option<Window> {
self.space
.elements()
.find(|window| window.wl_surface().map(|s| s == *surface).unwrap_or(false))
.cloned()
2023-06-30 21:34:07 -05:00
.or_else(|| {
self.windows
.iter()
.find(|&win| win.toplevel().wl_surface() == surface)
.cloned()
})
}
}
/// Toggle a window's floating status.
2023-06-18 19:30:52 -05:00
pub fn toggle_floating<B: Backend>(state: &mut State<B>, window: &Window) {
2023-07-09 10:00:16 -05:00
WindowState::with(window, |window_state| {
2023-05-28 19:14:30 -05:00
match window_state.floating {
2023-06-18 19:30:52 -05:00
Float::Tiled(prev_loc_and_size) => {
2023-05-28 19:14:30 -05:00
if let Some((prev_loc, prev_size)) = prev_loc_and_size {
window.toplevel().with_pending_state(|state| {
state.size = Some(prev_size);
});
window.toplevel().send_pending_configure();
2023-06-18 19:30:52 -05:00
state.space.map_element(window.clone(), prev_loc, false); // TODO: should it activate?
2023-05-28 19:14:30 -05:00
}
2023-06-18 19:30:52 -05:00
window_state.floating = Float::Floating;
2023-05-28 19:14:30 -05:00
}
Float::Floating => {
2023-06-18 19:30:52 -05:00
window_state.floating = Float::Tiled(Some((
2023-06-19 12:42:49 -05:00
// We get the location this way because window.geometry().loc
// doesn't seem to be the actual location
state.space.element_location(window).unwrap(),
2023-05-28 19:14:30 -05:00
window.geometry().size,
)));
}
}
2023-06-18 19:30:52 -05:00
});
2023-07-09 10:00:16 -05:00
state.re_layout();
2023-07-09 17:48:46 -05:00
let output = state.focus_state.focused_output.as_ref().unwrap();
let render = OutputState::with(output, |op_state| {
state
.windows
.iter()
.cloned()
.filter(|win| {
WindowState::with(win, |win_state| {
if win_state.floating.is_floating() {
return true;
}
for tag_id in win_state.tags.iter() {
if op_state.focused_tags().any(|tag| &tag.id == tag_id) {
return true;
}
}
false
})
})
.collect::<Vec<_>>()
});
let clone = window.clone();
state.schedule_on_commit(render, move |data| {
data.state.space.raise_element(&clone, true);
2023-07-09 17:48:46 -05:00
});
2023-05-28 19:14:30 -05:00
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct WindowProperties {
pub id: WindowId,
pub app_id: Option<String>,
pub title: Option<String>,
/// Width and height
pub size: (i32, i32),
/// x and y
pub location: (i32, i32),
pub floating: bool,
}