X11: Continuous Presentation (#7762)

Alternative to #7758, which doesn't involve adding a new trait method
`request_draw`.
Somehow, my whole screen goes blinking black with this when moving the
window, so not ready for landing.

Release Notes:
- N/A

---------

Co-authored-by: Mikayla Maki <mikayla@zed.dev>
This commit is contained in:
Dzmitry Malyshau
2024-02-14 12:24:12 -08:00
committed by GitHub
co-authored by Mikayla Maki
parent 181f556269
commit 8f7a26f397
9 changed files with 78 additions and 23 deletions
+3 -1
View File
@@ -64,7 +64,9 @@ impl Default for LinuxPlatform {
impl LinuxPlatform {
pub(crate) fn new() -> Self {
let (xcb_connection, x_root_index) = xcb::Connection::connect(None).unwrap();
let (xcb_connection, x_root_index) =
xcb::Connection::connect_with_extensions(None, &[xcb::Extension::Present], &[])
.unwrap();
let atoms = XcbAtoms::intern_all(&xcb_connection).unwrap();
let xcb_connection = Arc::new(xcb_connection);
+16 -12
View File
@@ -41,6 +41,11 @@ impl X11Client {
}),
}
}
fn get_window(&self, win: x::Window) -> Rc<X11WindowState> {
let state = self.state.lock();
Rc::clone(&state.windows[&win])
}
}
impl Client for X11Client {
@@ -58,18 +63,14 @@ impl Client for X11Client {
// window "x" button clicked by user, we gracefully exit
let window = self.state.lock().windows.remove(&ev.window()).unwrap();
window.destroy();
let mut state = self.state.lock();
let state = self.state.lock();
self.platform_inner.state.lock().quit_requested |=
state.windows.is_empty();
}
}
}
xcb::Event::X(x::Event::Expose(ev)) => {
let window = {
let state = self.state.lock();
Rc::clone(&state.windows[&ev.window()])
};
window.expose();
self.get_window(ev.window()).refresh();
}
xcb::Event::X(x::Event::ConfigureNotify(ev)) => {
let bounds = Bounds {
@@ -82,12 +83,14 @@ impl Client for X11Client {
height: ev.height().into(),
},
};
let window = {
let state = self.state.lock();
Rc::clone(&state.windows[&ev.window()])
};
window.configure(bounds)
self.get_window(ev.window()).configure(bounds)
}
xcb::Event::Present(xcb::present::Event::CompleteNotify(ev)) => {
let window = self.get_window(ev.window());
window.refresh();
window.request_refresh();
}
xcb::Event::Present(xcb::present::Event::IdleNotify(_ev)) => {}
_ => {}
}
@@ -117,7 +120,7 @@ impl Client for X11Client {
fn open_window(
&self,
handle: AnyWindowHandle,
_handle: AnyWindowHandle,
options: WindowOptions,
) -> Box<dyn PlatformWindow> {
let x_window = self.xcb_connection.generate_id();
@@ -129,6 +132,7 @@ impl Client for X11Client {
x_window,
&self.atoms,
));
window_ptr.request_refresh();
self.state
.lock()
+23 -1
View File
@@ -202,6 +202,16 @@ impl X11WindowState {
})
.unwrap();
let fake_id = xcb_connection.generate_id();
xcb_connection
.send_and_check_request(&xcb::present::SelectInput {
eid: fake_id,
window: x_window,
//Note: also consider `IDLE_NOTIFY`
event_mask: xcb::present::EventMask::COMPLETE_NOTIFY,
})
.unwrap();
xcb_connection.send_request(&x::MapWindow { window: x_window });
xcb_connection.flush().unwrap();
@@ -258,7 +268,7 @@ impl X11WindowState {
self.xcb_connection.flush().unwrap();
}
pub fn expose(&self) {
pub fn refresh(&self) {
let mut cb = self.callbacks.lock();
if let Some(ref mut fun) = cb.request_frame {
fun();
@@ -291,6 +301,18 @@ impl X11WindowState {
}
}
}
pub fn request_refresh(&self) {
self.xcb_connection
.send_and_check_request(&xcb::present::NotifyMsc {
window: self.x_window,
serial: 0,
target_msc: 0,
divisor: 1,
remainder: 0,
})
.unwrap();
}
}
impl PlatformWindow for X11Window {