1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-26 23:04:49 +03:00

Implement most of dispatch pending_event

This commit is contained in:
Timmy Xiao 2024-01-07 21:57:52 -05:00 committed by Wez Furlong
parent 3496aff490
commit b01e32b606
No known key found for this signature in database
GPG Key ID: 7A7F66A31EC9B387
2 changed files with 151 additions and 90 deletions

View File

@ -1,7 +1,7 @@
// TODO: change this // TODO: change this
#![allow(dead_code, unused)] #![allow(dead_code, unused)]
use std::{ use std::{
cell::RefCell, cell::{RefCell, Ref},
collections::HashMap, collections::HashMap,
os::fd::AsRawFd, os::fd::AsRawFd,
rc::Rc, rc::Rc,
@ -20,7 +20,7 @@ use smithay_client_toolkit::{
shell::{ shell::{
xdg::window::{WindowHandler, WindowState as SCTKWindowState}, xdg::window::{WindowHandler, WindowState as SCTKWindowState},
WaylandSurface, WaylandSurface,
}, }, shm::{slot::SlotPool, Shm, ShmHandler}, delegate_shm,
}; };
use wayland_client::{ use wayland_client::{
backend::WaylandError, backend::WaylandError,
@ -41,27 +41,34 @@ pub struct WaylandConnection {
pub(crate) gl_connection: RefCell<Option<Rc<crate::egl::GlConnection>>>, pub(crate) gl_connection: RefCell<Option<Rc<crate::egl::GlConnection>>>,
pub(crate) globals: RefCell<GlobalList>,
pub(crate) connection: RefCell<WConnection>, pub(crate) connection: RefCell<WConnection>,
pub(crate) event_queue: RefCell<EventQueue<WaylandState>>, pub(crate) event_queue: RefCell<EventQueue<WaylandState>>,
pub(crate) globals: RefCell<GlobalList>,
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? // 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,
shm: Shm,
pub(crate) mem_pool: RefCell<SlotPool>,
} }
impl WaylandConnection { impl WaylandConnection {
pub(crate) fn create_new() -> anyhow::Result<Self> { pub(crate) fn create_new() -> anyhow::Result<Self> {
let conn = WConnection::connect_to_env()?; let conn = WConnection::connect_to_env()?;
let (globals, event_queue) = registry_queue_init::<WaylandState>(&conn)?; let (globals, event_queue) = registry_queue_init::<WaylandState>(&conn)?;
let _qh = event_queue.handle(); let qh = event_queue.handle();
let shm = Shm::bind(&globals, &qh)?;
let mem_pool = SlotPool::new(1, &shm)?;
let wayland_state = WaylandState { let wayland_state = WaylandState {
registry_state: RegistryState::new(&globals), registry_state: RegistryState::new(&globals),
shm,
mem_pool: RefCell::new(mem_pool),
}; };
let wayland_connection = WaylandConnection { let wayland_connection = WaylandConnection {
connection: RefCell::new(conn), connection: RefCell::new(conn),
should_terminate: RefCell::new(false), should_terminate: RefCell::new(false),
@ -334,6 +341,12 @@ impl WindowHandler for WaylandState {
} }
} }
impl ShmHandler for WaylandState {
fn shm_state(&mut self) -> &mut Shm {
&mut self.shm
}
}
impl ConnectionOps for WaylandConnection { impl ConnectionOps for WaylandConnection {
fn name(&self) -> String { fn name(&self) -> String {
"Wayland".to_string() "Wayland".to_string()
@ -368,6 +381,8 @@ delegate_output!(WaylandState);
delegate_xdg_shell!(WaylandState); delegate_xdg_shell!(WaylandState);
delegate_xdg_window!(WaylandState); delegate_xdg_window!(WaylandState);
delegate_shm!(WaylandState);
delegate_registry!(WaylandState); delegate_registry!(WaylandState);
impl ProvidesRegistryState for WaylandState { impl ProvidesRegistryState for WaylandState {

View File

@ -4,6 +4,7 @@
use std::any::Any; use std::any::Any;
use std::cell::RefCell; use std::cell::RefCell;
use std::convert::TryInto;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;
@ -43,8 +44,10 @@ use crate::wayland::WaylandConnection;
use crate::Clipboard; use crate::Clipboard;
use crate::Connection; use crate::Connection;
use crate::ConnectionOps; use crate::ConnectionOps;
use crate::Dimensions;
use crate::MouseCursor; use crate::MouseCursor;
use crate::RequestedWindowGeometry; use crate::RequestedWindowGeometry;
use crate::ResolvedGeometry;
use crate::Window; use crate::Window;
use crate::WindowEvent; use crate::WindowEvent;
use crate::WindowEventSender; use crate::WindowEventSender;
@ -98,6 +101,19 @@ impl WaylandWindow {
}; };
let surface = compositor.create_surface_with_data(&qh, surface_data); let surface = compositor.create_surface_with_data(&qh, surface_data);
let ResolvedGeometry {
x: _,
y: _,
width,
height,
} = conn.resolve_geometry(geometry);
let dimensions = Dimensions {
pixel_width: width,
pixel_height: height,
dpi: config.dpi.unwrap_or(crate::DEFAULT_DPI) as usize,
};
let xdg_shell = XdgShell::bind(&globals, &qh)?; let xdg_shell = XdgShell::bind(&globals, &qh)?;
let window = xdg_shell.create_window(surface.clone(), Decorations::RequestServer, &qh); let window = xdg_shell.create_window(surface.clone(), Decorations::RequestServer, &qh);
@ -116,7 +132,8 @@ impl WaylandWindow {
}; };
window.request_decoration_mode(decor_mode); window.request_decoration_mode(decor_mode);
// TODO: I don't know anything about the frame thing // TODO: I don't want to deal with CSD right now, since my current tiling window manager
// Hyprland doesn't support it
// window.set_frame_config(ConceptConfig { // window.set_frame_config(ConceptConfig {
window.set_min_size(Some((32, 32))); window.set_min_size(Some((32, 32)));
@ -129,14 +146,15 @@ impl WaylandWindow {
// conn.pointer.borrow().add_window(&surface, &pending_mouse); // conn.pointer.borrow().add_window(&surface, &pending_mouse);
// TODO: WindowInner
let inner = Rc::new(RefCell::new(WaylandWindowInner { let inner = Rc::new(RefCell::new(WaylandWindowInner {
window_id, window_id,
events: WindowEventSender::new(event_handler), events: WindowEventSender::new(event_handler),
surface_factor: 1.0,
invalidated: false, invalidated: false,
window: Some(window), window: Some(window),
dimensions,
resize_increments: None,
window_state: WindowState::default(), window_state: WindowState::default(),
pending_event, pending_event,
@ -144,6 +162,8 @@ impl WaylandWindow {
pending_first_configure: Some(pending_first_configure), pending_first_configure: Some(pending_first_configure),
frame_callback: None, frame_callback: None,
config,
title: None, title: None,
wegl_surface: None, wegl_surface: None,
@ -279,11 +299,11 @@ pub(crate) struct PendingEvent {
pub struct WaylandWindowInner { pub struct WaylandWindowInner {
window_id: usize, window_id: usize,
pub(crate) events: WindowEventSender, pub(crate) events: WindowEventSender,
// surface_factor: f64, surface_factor: f64,
// copy_and_paste: Arc<Mutex<CopyAndPaste>>, // copy_and_paste: Arc<Mutex<CopyAndPaste>>,
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,
@ -300,7 +320,7 @@ pub struct WaylandWindowInner {
// font_config: Rc<FontConfiguration>, // font_config: Rc<FontConfiguration>,
// text_cursor: Option<Rect>, // text_cursor: Option<Rect>,
// appearance: Appearance, // appearance: Appearance,
// config: ConfigHandle, config: ConfigHandle,
// // cache the title for comparison to avoid spamming // // cache the title for comparison to avoid spamming
// // the compositor with updates that don't actually change it // // the compositor with updates that don't actually change it
title: Option<String>, title: Option<String>,
@ -323,8 +343,9 @@ impl WaylandWindowInner {
fn refresh_frame(&mut self) { fn refresh_frame(&mut self) {
if let Some(window) = self.window.as_mut() { if let Some(window) = self.window.as_mut() {
// TODO: refresh frame
// window.refresh(); // window.refresh();
// window.surface().commit(); window.wl_surface().commit();
} }
} }
@ -383,6 +404,21 @@ impl WaylandWindowInner {
Ok(gl_state) Ok(gl_state)
} }
fn get_dpi_factor(&self) -> f64 {
self.dimensions.dpi as f64 / crate::DEFAULT_DPI as f64
}
fn surface_to_pixels(&self, surface: i32) -> i32 {
(surface as f64 * self.get_dpi_factor()).ceil() as i32
}
fn pixels_to_surface(&self, pixels: i32) -> i32 {
// Take care to round up, otherwise we can lose a pixel
// and that can effectively lose the final row of the
// terminal
((pixels as f64) / self.get_dpi_factor()).ceil() as i32
}
pub(crate) fn dispatch_pending_event(&mut self) { pub(crate) fn dispatch_pending_event(&mut self) {
let mut pending; let mut pending;
{ {
@ -405,95 +441,105 @@ impl WaylandWindowInner {
} }
if pending.configure.is_none() { if pending.configure.is_none() {
// TODO: Handle the DPI if pending.dpi.is_some() {
// Synthesize a pending configure event for the dpi change
pending.configure.replace((
self.pixels_to_surface(self.dimensions.pixel_width as i32) as u32,
self.pixels_to_surface(self.dimensions.pixel_height as i32) as u32,
));
log::debug!("synthesize configure with {:?}", pending.configure);
}
} }
if let Some((mut w, mut h)) = pending.configure.take() { if let Some((mut w, mut h)) = pending.configure.take() {
log::trace!("Pending configure: w:{w}, h{h} -- {:?}", self.window); log::trace!("Pending configure: w:{w}, h{h} -- {:?}", self.window);
if self.window.is_some() { if self.window.is_some() {
// TODO: here let surface_udata = SurfaceUserData::from_wl(self.surface());
// let factor = get_surface_scale_factor(&self.surface) as f64; let factor = surface_udata.surface_data.scale_factor() as f64;
// let old_dimensions = self.dimensions; let old_dimensions = self.dimensions;
// FIXME: teach this how to resolve dpi_by_screen // FIXME: teach this how to resolve dpi_by_screen
// let dpi = self.config.dpi.unwrap_or(factor * crate::DEFAULT_DPI) as usize; 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 // Do this early because this affects surface_to_pixels/pixels_to_surface
// self.dimensions.dpi = dpi; self.dimensions.dpi = dpi;
// let mut pixel_width = self.surface_to_pixels(w.try_into().unwrap()); let mut pixel_width = self.surface_to_pixels(w.try_into().unwrap());
// let mut pixel_height = self.surface_to_pixels(h.try_into().unwrap()); let mut pixel_height = self.surface_to_pixels(h.try_into().unwrap());
//
// if self.window_state.can_resize() { if self.window_state.can_resize() {
// if let Some((x, y)) = self.resize_increments { if let Some((x, y)) = self.resize_increments {
// let desired_pixel_width = pixel_width - (pixel_width % x as i32); let desired_pixel_width = pixel_width - (pixel_width % x as i32);
// let desired_pixel_height = pixel_height - (pixel_height % y as i32); let desired_pixel_height = pixel_height - (pixel_height % y as i32);
// w = self.pixels_to_surface(desired_pixel_width) as u32; w = self.pixels_to_surface(desired_pixel_width) as u32;
// h = self.pixels_to_surface(desired_pixel_height) as u32; h = self.pixels_to_surface(desired_pixel_height) as u32;
// pixel_width = self.surface_to_pixels(w.try_into().unwrap()); pixel_width = self.surface_to_pixels(w.try_into().unwrap());
// pixel_height = self.surface_to_pixels(h.try_into().unwrap()); pixel_height = self.surface_to_pixels(h.try_into().unwrap());
// } }
// } }
//
// // Update the window decoration size // TODO: Update the window decoration size
// self.window.as_mut().unwrap().resize(w, h); // self.window.as_mut().unwrap().resize(w, h);
//
// // Compute the new pixel dimensions // Compute the new pixel dimensions
// let new_dimensions = Dimensions { let new_dimensions = Dimensions {
// pixel_width: pixel_width.try_into().unwrap(), pixel_width: pixel_width.try_into().unwrap(),
// pixel_height: pixel_height.try_into().unwrap(), pixel_height: pixel_height.try_into().unwrap(),
// dpi, dpi,
// }; };
//
// // Only trigger a resize if the new dimensions are different; // Only trigger a resize if the new dimensions are different;
// // this makes things more efficient and a little more smooth // this makes things more efficient and a little more smooth
// if new_dimensions != old_dimensions { if new_dimensions != old_dimensions {
// self.dimensions = new_dimensions; self.dimensions = new_dimensions;
//
// self.events.dispatch(WindowEvent::Resized { self.events.dispatch(WindowEvent::Resized {
// dimensions: self.dimensions, dimensions: self.dimensions,
// window_state: self.window_state, window_state: self.window_state,
// // We don't know if we're live resizing or not, so // We don't know if we're live resizing or not, so
// // assume no. // assume no.
// live_resizing: false, live_resizing: false,
// }); });
// // Avoid blurring by matching the scaling factor of the // Avoid blurring by matching the scaling factor of the
// // compositor; if it is going to double the size then // compositor; if it is going to double the size then
// // we render at double the size anyway and tell it that // we render at double the size anyway and tell it that
// // the buffer is already doubled. // the buffer is already doubled.
// // Take care to detach the current buffer (managed by EGL), // Take care to detach the current buffer (managed by EGL),
// // so that the compositor doesn't get annoyed by it not // so that the compositor doesn't get annoyed by it not
// // having dimensions that match the scale. // having dimensions that match the scale.
// // The wegl_surface.resize won't take effect until // The wegl_surface.resize won't take effect until
// // we paint later on. // we paint later on.
// // We do this only if the scale has actually changed, // We do this only if the scale has actually changed,
// // otherwise interactive window resize will keep removing // otherwise interactive window resize will keep removing
// // the window contents! // the window contents!
// if let Some(wegl_surface) = self.wegl_surface.as_mut() { if let Some(wegl_surface) = self.wegl_surface.as_mut() {
// wegl_surface.resize(pixel_width, pixel_height, 0, 0); wegl_surface.resize(pixel_width, pixel_height, 0, 0);
// } }
// if self.surface_factor != factor { if self.surface_factor != factor {
// let wayland_conn = Connection::get().unwrap().wayland(); let wayland_conn = Connection::get().unwrap().wayland();
// let mut pool = wayland_conn.mem_pool.borrow_mut(); let wayland_state = wayland_conn.wayland_state.borrow();
// // Make a "fake" buffer with the right dimensions, as let mut pool = wayland_state.mem_pool.borrow_mut();
// // simply detaching the buffer can cause wlroots-derived
// // compositors consider the window to be unconfigured. // Make a "fake" buffer with the right dimensions, as
// if let Ok((_bytes, buffer)) = pool.buffer( // simply detaching the buffer can cause wlroots-derived
// factor as i32, // compositors consider the window to be unconfigured.
// factor as i32, if let Ok((buffer, _bytes)) = pool.create_buffer(
// (factor * 4.0) as i32, factor as i32,
// wayland_client::protocol::wl_shm::Format::Argb8888, factor as i32,
// ) { (factor * 4.0) as i32,
// self.surface.attach(Some(&buffer), 0, 0); wayland_client::protocol::wl_shm::Format::Argb8888,
// self.surface.set_buffer_scale(factor as i32); ) {
// self.surface_factor = factor; self.surface().attach(Some(buffer.wl_buffer()), 0, 0);
// } self.surface().set_buffer_scale(factor as i32);
// } self.surface_factor = factor;
// } }
// self.refresh_frame(); }
// self.do_paint().unwrap(); }
self.refresh_frame();
self.do_paint().unwrap();
} }
} }
// TODO:
// if pending.refresh_decorations && self.window.is_some() { // if pending.refresh_decorations && self.window.is_some() {
// self.refresh_frame(); // self.refresh_frame();
// } // }
@ -522,7 +568,7 @@ impl WaylandWindowInner {
if let Some(window) = self.window.as_ref() { if let Some(window) = self.window.as_ref() {
window.set_title(title.clone()); window.set_title(title.clone());
} }
// TODO: self.refresh_frame(); self.refresh_frame();
self.title = Some(title); self.title = Some(title);
} }