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:
parent
3496aff490
commit
b01e32b606
@ -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 {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user