alex/beta-minecraft-rust
Minecraft Beta 1.7.3 Rewrite
BRANCH main
SNAPSHOT Draw terrain GPU-driven from packed per-section buffers with GPU occlusion culling, add a render distance slider (2-128) with a quad/disk shape, cut chunk bookkeeping at high render distances, and fix a light underflow at y=0
DOWNLOAD
root crates client src app warp.rs
use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle};
use wayland_client::backend::{Backend, InvalidId, ObjectId, WaylandError};
use wayland_client::globals::{GlobalError, GlobalListContents, registry_queue_init};
use wayland_client::protocol::wl_pointer::{self, WlPointer};
use wayland_client::protocol::wl_registry::{self, WlRegistry};
use wayland_client::protocol::wl_seat::{self, WlSeat};
use wayland_client::protocol::wl_surface::WlSurface;
use wayland_client::{
Connection, Dispatch, DispatchError, EventQueue, Proxy, QueueHandle, WEnum, delegate_noop,
};
use wayland_protocols::wp::pointer_warp::v1::client::wp_pointer_warp_v1::WpPointerWarpV1;
use winit::window::Window;
#[derive(Debug, thiserror::Error)]
pub enum WarpError {
#[error(transparent)]
Handle(#[from] raw_window_handle::HandleError),
#[error(transparent)]
Global(#[from] GlobalError),
#[error(transparent)]
Id(#[from] InvalidId),
#[error(transparent)]
Dispatch(#[from] DispatchError),
#[error(transparent)]
Wayland(#[from] WaylandError),
}
/// Moves the pointer through `wp_pointer_warp_v1` on winit's Wayland connection, using a
/// dedicated `wl_pointer` to learn the enter serial winit keeps private.
pub struct PointerWarp {
queue: EventQueue<State>,
state: State,
manager: WpPointerWarpV1,
surface: WlSurface,
}
#[derive(Default)]
struct State {
pointer: Option<WlPointer>,
serial: Option<u32>,
}
impl PointerWarp {
/// `None` when not on Wayland or the compositor lacks the protocol.
pub fn new(window: &Window) -> Result<Option<Self>, WarpError> {
let (RawDisplayHandle::Wayland(display), RawWindowHandle::Wayland(surface)) = (
window.display_handle()?.as_raw(),
window.window_handle()?.as_raw(),
) else {
return Ok(None);
};
// Safety: winit keeps the display and surface alive for as long as the window
let backend = unsafe { Backend::from_foreign_display(display.display.as_ptr().cast()) };
let connection = Connection::from_backend(backend);
let surface =
unsafe { ObjectId::from_ptr(WlSurface::interface(), surface.surface.as_ptr().cast()) }?;
let surface = WlSurface::from_id(&connection, surface)?;
let (globals, mut queue) = registry_queue_init::<State>(&connection)?;
let handle = queue.handle();
let (Ok(manager), Ok(_)) = (
globals.bind::<WpPointerWarpV1, _, _>(&handle, 1..=1, ()),
globals.bind::<WlSeat, _, _>(&handle, 1..=5, ()),
) else {
return Ok(None);
};
let mut state = State::default();
queue.roundtrip(&mut state)?;
Ok(Some(Self {
queue,
state,
manager,
surface,
}))
}
/// Warps to a surface-local logical position; `false` while the pointer is outside.
pub fn warp(&mut self, x: f64, y: f64) -> Result<bool, WarpError> {
self.queue.dispatch_pending(&mut self.state)?;
let (Some(pointer), Some(serial)) = (&self.state.pointer, self.state.serial) else {
return Ok(false);
};
self.manager
.warp_pointer(&self.surface, pointer, x, y, serial);
self.queue.flush()?;
Ok(true)
}
}
impl Dispatch<WlRegistry, GlobalListContents> for State {
fn event(
_: &mut Self,
_: &WlRegistry,
_: wl_registry::Event,
_: &GlobalListContents,
_: &Connection,
_: &QueueHandle<Self>,
) {
}
}
impl Dispatch<WlSeat, ()> for State {
fn event(
state: &mut Self,
seat: &WlSeat,
event: wl_seat::Event,
_: &(),
_: &Connection,
handle: &QueueHandle<Self>,
) {
if let wl_seat::Event::Capabilities {
capabilities: WEnum::Value(capabilities),
} = event
&& capabilities.contains(wl_seat::Capability::Pointer)
&& state.pointer.is_none()
{
state.pointer = Some(seat.get_pointer(handle, ()));
}
}
}
impl Dispatch<WlPointer, ()> for State {
fn event(
state: &mut Self,
_: &WlPointer,
event: wl_pointer::Event,
_: &(),
_: &Connection,
_: &QueueHandle<Self>,
) {
match event {
wl_pointer::Event::Enter { serial, .. } => state.serial = Some(serial),
wl_pointer::Event::Leave { .. } => state.serial = None,
_ => {}
}
}
}
delegate_noop!(State: ignore WpPointerWarpV1);