1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-25 22:33:52 +03:00

Implement handling window configuration

This commit is contained in:
Timmy Xiao 2024-01-06 20:52:09 -05:00 committed by Wez Furlong
parent d429fe1a7d
commit 0348a584c7
No known key found for this signature in database
GPG Key ID: 7A7F66A31EC9B387
2 changed files with 217 additions and 21 deletions

View File

@ -1,7 +1,11 @@
// TODO: change this // TODO: change this
#![allow(dead_code, unused)] #![allow(dead_code, unused)]
use std::{ use std::{
cell::RefCell, collections::HashMap, os::fd::AsRawFd, rc::Rc, sync::atomic::AtomicUsize, cell::RefCell,
collections::HashMap,
os::fd::AsRawFd,
rc::Rc,
sync::{atomic::AtomicUsize, Arc},
}; };
use anyhow::{bail, Context}; use anyhow::{bail, Context};
@ -13,16 +17,19 @@ use smithay_client_toolkit::{
output::{OutputHandler, OutputState}, output::{OutputHandler, OutputState},
registry::{ProvidesRegistryState, RegistryState}, registry::{ProvidesRegistryState, RegistryState},
registry_handlers, registry_handlers,
shell::xdg::window::WindowHandler, shell::{
xdg::window::{WindowHandler, WindowState as SCTKWindowState},
WaylandSurface,
},
}; };
use wayland_client::{ use wayland_client::{
backend::WaylandError, backend::WaylandError,
globals::{registry_queue_init, GlobalList}, globals::{registry_queue_init, GlobalList},
protocol::wl_surface::WlSurface, protocol::wl_surface::WlSurface,
Connection as WConnection, EventQueue, Connection as WConnection, EventQueue, Proxy,
}; };
use crate::{spawn::SPAWN_QUEUE, Connection, ConnectionOps}; use crate::{spawn::SPAWN_QUEUE, Connection, ConnectionOps, WindowState};
use super::{SurfaceUserData, WaylandWindowInner}; use super::{SurfaceUserData, WaylandWindowInner};
@ -41,6 +48,7 @@ pub struct WaylandConnection {
pub(crate) wayland_state: RefCell<WaylandState>, pub(crate) wayland_state: RefCell<WaylandState>,
} }
// TODO: the SurfaceUserData should be something in WaylandConnection struct as a whole. I think?
pub(crate) struct WaylandState { pub(crate) struct WaylandState {
registry_state: RegistryState, registry_state: RegistryState,
} }
@ -126,9 +134,6 @@ impl WaylandConnection {
continue; continue;
} }
println!("READING WL EVENT");
let a = event_q.prepare_read();
if let Ok(guard) = event_q.prepare_read() { if let Ok(guard) = event_q.prepare_read() {
if let Err(err) = guard.read() { if let Err(err) = guard.read() {
log::trace!("Event Q error: {:?}", err); log::trace!("Event Q error: {:?}", err);
@ -261,9 +266,66 @@ impl WindowHandler for WaylandState {
configure: smithay_client_toolkit::shell::xdg::window::WindowConfigure, configure: smithay_client_toolkit::shell::xdg::window::WindowConfigure,
serial: u32, serial: u32,
) { ) {
// How can i get the specific pending state for the window let surface_data = SurfaceUserData::from_wl(window.wl_surface());
log::trace!("Configuring Window Handler"); // TODO: XXX: should we grouping window data and connection
todo!()
let window_id = surface_data.window_id;
let wconn = WaylandConnection::get()
.expect("should be wayland connection")
.wayland();
let window_inner = wconn
.window_by_id(window_id)
.expect("Inner Window should exist");
let p = window_inner.borrow().pending_event.clone();
let mut pending_event = p.lock().unwrap();
// TODO: This should the new queue function
// p.queue_configure(&configure)
//
let changed = {
let mut changed;
pending_event.had_configure_event = true;
if let (Some(w), Some(h)) = configure.new_size {
changed = pending_event.configure.is_none();
pending_event.configure.replace((w.get(), h.get()));
} else {
changed = true;
}
let mut state = WindowState::default();
if configure.state.contains(SCTKWindowState::FULLSCREEN) {
state |= WindowState::FULL_SCREEN;
}
let fs_bits = SCTKWindowState::MAXIMIZED
| SCTKWindowState::TILED_LEFT
| SCTKWindowState::TILED_RIGHT
| SCTKWindowState::TILED_TOP
| SCTKWindowState::TILED_BOTTOM;
if !((configure.state & fs_bits).is_empty()) {
state |= WindowState::MAXIMIZED;
}
log::debug!(
"Config: self.window_state={:?}, states: {:?} {:?}",
pending_event.window_state,
state,
configure.state
);
if pending_event.window_state.is_none() && state != WindowState::default() {
changed = true;
}
pending_event.window_state.replace(state);
changed
}; // function should return changed
if changed {
WaylandConnection::with_window_inner(window_id, move |inner| {
inner.dispatch_pending_event();
Ok(())
});
}
} }
} }

View File

@ -1,4 +1,5 @@
// TODO: change this // TODO: change this
// TODO: change a lot of the pubstruct crates
#![allow(dead_code, unused)] #![allow(dead_code, unused)]
use std::any::Any; use std::any::Any;
@ -47,6 +48,7 @@ use crate::Window;
use crate::WindowEvent; use crate::WindowEvent;
use crate::WindowEventSender; use crate::WindowEventSender;
use crate::WindowOps; use crate::WindowOps;
use crate::WindowState;
#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)] #[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct WaylandWindow(usize); pub struct WaylandWindow(usize);
@ -131,8 +133,12 @@ impl WaylandWindow {
events: WindowEventSender::new(event_handler), events: WindowEventSender::new(event_handler),
window: Some(window), window: Some(window),
window_state: WindowState::default(),
pending_event, pending_event,
pending_first_configure: Some(pending_first_configure),
wegl_surface: None, wegl_surface: None,
gl_state: None, gl_state: None,
})); }));
@ -165,7 +171,6 @@ impl WaylandWindow {
#[async_trait(?Send)] #[async_trait(?Send)]
impl WindowOps for WaylandWindow { impl WindowOps for WaylandWindow {
#[doc = r" Show a hidden window"]
fn show(&self) { fn show(&self) {
WaylandConnection::with_window_inner(self.0, |inner| { WaylandConnection::with_window_inner(self.0, |inner| {
inner.show(); inner.show();
@ -258,12 +263,12 @@ unsafe impl HasRawWindowHandle for WaylandWindow {
} }
#[derive(Default, Clone, Debug)] #[derive(Default, Clone, Debug)]
struct PendingEvent { pub(crate) struct PendingEvent {
close: bool, pub(crate) close: bool,
had_configure_event: bool, pub(crate) had_configure_event: bool,
configure: Option<(u32, u32)>, pub(crate) configure: Option<(u32, u32)>,
dpi: Option<i32>, pub(crate) dpi: Option<i32>,
// window_state: Option<WindowState>, pub(crate) window_state: Option<WindowState>,
} }
pub struct WaylandWindowInner { pub struct WaylandWindowInner {
@ -274,7 +279,7 @@ pub struct WaylandWindowInner {
window: Option<XdgWindow>, window: Option<XdgWindow>,
// dimensions: Dimensions, // dimensions: Dimensions,
// resize_increments: Option<(u16, u16)>, // resize_increments: Option<(u16, u16)>,
// window_state: WindowState, window_state: WindowState,
// last_mouse_coords: Point, // last_mouse_coords: Point,
// mouse_buttons: MouseButtons, // mouse_buttons: MouseButtons,
// hscroll_remainder: f64, // hscroll_remainder: f64,
@ -282,9 +287,9 @@ pub struct WaylandWindowInner {
// modifiers: Modifiers, // modifiers: Modifiers,
// leds: KeyboardLedStatus, // leds: KeyboardLedStatus,
// key_repeat: Option<(u32, Arc<Mutex<KeyRepeatState>>)>, // key_repeat: Option<(u32, Arc<Mutex<KeyRepeatState>>)>,
pending_event: Arc<Mutex<PendingEvent>>, pub(crate) pending_event: Arc<Mutex<PendingEvent>>,
// pending_mouse: Arc<Mutex<PendingMouse>>, // pending_mouse: Arc<Mutex<PendingMouse>>,
// pending_first_configure: Option<async_channel::Sender<()>>, pending_first_configure: Option<async_channel::Sender<()>>,
// frame_callback: Option<Main<WlCallback>>, // frame_callback: Option<Main<WlCallback>>,
// invalidated: bool, // invalidated: bool,
// font_config: Rc<FontConfiguration>, // font_config: Rc<FontConfiguration>,
@ -361,6 +366,128 @@ impl WaylandWindowInner {
Ok(gl_state) Ok(gl_state)
} }
pub(crate) fn dispatch_pending_event(&mut self) {
let mut pending;
{
let mut pending_events = self.pending_event.lock().unwrap();
pending = pending_events.clone();
*pending_events = PendingEvent::default();
}
if pending.close {
self.events.dispatch(WindowEvent::CloseRequested);
}
if let Some(window_state) = pending.window_state.take() {
log::debug!(
"dispatch_pending_event self.window_state={:?}, pending:{:?}",
window_state,
window_state
);
self.window_state = window_state;
}
if pending.configure.is_none() {
// TODO: Handle the DPI
}
if let Some((mut w, mut h)) = pending.configure.take() {
log::trace!("Pending configure: w:{w}, h{h} -- {:?}", self.window);
if self.window.is_some() {
// TODO: here
// let factor = get_surface_scale_factor(&self.surface) as f64;
// let old_dimensions = self.dimensions;
// FIXME: teach this how to resolve dpi_by_screen
// let dpi = self.config.dpi.unwrap_or(factor * crate::DEFAULT_DPI) as usize;
// Do this early because this affects surface_to_pixels/pixels_to_surface
// self.dimensions.dpi = dpi;
// let mut pixel_width = self.surface_to_pixels(w.try_into().unwrap());
// let mut pixel_height = self.surface_to_pixels(h.try_into().unwrap());
//
// if self.window_state.can_resize() {
// if let Some((x, y)) = self.resize_increments {
// let desired_pixel_width = pixel_width - (pixel_width % x as i32);
// let desired_pixel_height = pixel_height - (pixel_height % y as i32);
// w = self.pixels_to_surface(desired_pixel_width) as u32;
// h = self.pixels_to_surface(desired_pixel_height) as u32;
// pixel_width = self.surface_to_pixels(w.try_into().unwrap());
// pixel_height = self.surface_to_pixels(h.try_into().unwrap());
// }
// }
//
// // Update the window decoration size
// self.window.as_mut().unwrap().resize(w, h);
//
// // Compute the new pixel dimensions
// let new_dimensions = Dimensions {
// pixel_width: pixel_width.try_into().unwrap(),
// pixel_height: pixel_height.try_into().unwrap(),
// dpi,
// };
//
// // Only trigger a resize if the new dimensions are different;
// // this makes things more efficient and a little more smooth
// if new_dimensions != old_dimensions {
// self.dimensions = new_dimensions;
//
// self.events.dispatch(WindowEvent::Resized {
// dimensions: self.dimensions,
// window_state: self.window_state,
// // We don't know if we're live resizing or not, so
// // assume no.
// live_resizing: false,
// });
// // Avoid blurring by matching the scaling factor of the
// // compositor; if it is going to double the size then
// // we render at double the size anyway and tell it that
// // the buffer is already doubled.
// // Take care to detach the current buffer (managed by EGL),
// // so that the compositor doesn't get annoyed by it not
// // having dimensions that match the scale.
// // The wegl_surface.resize won't take effect until
// // we paint later on.
// // We do this only if the scale has actually changed,
// // otherwise interactive window resize will keep removing
// // the window contents!
// if let Some(wegl_surface) = self.wegl_surface.as_mut() {
// wegl_surface.resize(pixel_width, pixel_height, 0, 0);
// }
// if self.surface_factor != factor {
// let wayland_conn = Connection::get().unwrap().wayland();
// let mut pool = wayland_conn.mem_pool.borrow_mut();
// // Make a "fake" buffer with the right dimensions, as
// // simply detaching the buffer can cause wlroots-derived
// // compositors consider the window to be unconfigured.
// if let Ok((_bytes, buffer)) = pool.buffer(
// factor as i32,
// factor as i32,
// (factor * 4.0) as i32,
// wayland_client::protocol::wl_shm::Format::Argb8888,
// ) {
// self.surface.attach(Some(&buffer), 0, 0);
// self.surface.set_buffer_scale(factor as i32);
// self.surface_factor = factor;
// }
// }
// }
// self.refresh_frame();
// self.do_paint().unwrap();
}
}
// if pending.refresh_decorations && self.window.is_some() {
// self.refresh_frame();
// }
if pending.had_configure_event && self.window.is_some() {
if let Some(notify) = self.pending_first_configure.take() {
// Allow window creation to complete
notify.try_send(()).ok();
}
}
}
} }
unsafe impl HasRawDisplayHandle for WaylandWindowInner { unsafe impl HasRawDisplayHandle for WaylandWindowInner {
@ -388,7 +515,14 @@ unsafe impl HasRawWindowHandle for WaylandWindowInner {
pub(crate) struct SurfaceUserData { pub(crate) struct SurfaceUserData {
surface_data: SurfaceData, surface_data: SurfaceData,
window_id: usize, pub(crate) window_id: usize,
}
impl SurfaceUserData {
pub(crate) fn from_wl(wl: &WlSurface) -> &Self {
wl.data()
.expect("User data should be associated with WlSurface")
}
} }
impl SurfaceDataExt for SurfaceUserData { impl SurfaceDataExt for SurfaceUserData {