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:
parent
d429fe1a7d
commit
0348a584c7
@ -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(())
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user