mirror of
https://github.com/YaLTeR/niri.git
synced 2024-10-26 20:04:05 +03:00
Add a 1 Hz fallback frame callback timer
gamescope + Minecraft with NeoForge throws an error upon starting if there are no frame callbacks, thus making it the first client that has a problem. Also, apparently, Veloren disconnects from server with VSync and no frame callbacks.
This commit is contained in:
parent
43aa2f95be
commit
ed8a6afe80
117
src/niri.rs
117
src/niri.rs
@ -39,7 +39,7 @@ use smithay::desktop::{
|
||||
use smithay::input::keyboard::{Layout as KeyboardLayout, XkbContextHandler};
|
||||
use smithay::input::pointer::{CursorIcon, CursorImageAttributes, CursorImageStatus, MotionEvent};
|
||||
use smithay::input::{Seat, SeatState};
|
||||
use smithay::output::{self, Output};
|
||||
use smithay::output::{self, Output, PhysicalProperties, Subpixel};
|
||||
use smithay::reexports::calloop::generic::Generic;
|
||||
use smithay::reexports::calloop::timer::{TimeoutAction, Timer};
|
||||
use smithay::reexports::calloop::{
|
||||
@ -118,6 +118,11 @@ use crate::{animation, niri_render_elements};
|
||||
const CLEAR_COLOR: [f32; 4] = [0.2, 0.2, 0.2, 1.];
|
||||
const CLEAR_COLOR_LOCKED: [f32; 4] = [0.3, 0.1, 0.1, 1.];
|
||||
|
||||
// We'll try to send frame callbacks at least once a second. We'll make a timer that fires once a
|
||||
// second, so with the worst timing the maximum interval between two frame callbacks for a surface
|
||||
// should be ~1.995 seconds.
|
||||
const FRAME_CALLBACK_THROTTLE: Option<Duration> = Some(Duration::from_millis(995));
|
||||
|
||||
pub struct Niri {
|
||||
pub config: Rc<RefCell<Config>>,
|
||||
|
||||
@ -967,6 +972,16 @@ impl Niri {
|
||||
}
|
||||
};
|
||||
|
||||
event_loop
|
||||
.insert_source(
|
||||
Timer::from_duration(Duration::from_secs(1)),
|
||||
|_, _, state| {
|
||||
state.niri.send_frame_callbacks_on_fallback_timer();
|
||||
TimeoutAction::ToDuration(Duration::from_secs(1))
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let socket_source = ListeningSocketSource::new_auto().unwrap();
|
||||
let socket_name = socket_source.socket_name().to_os_string();
|
||||
event_loop
|
||||
@ -2430,11 +2445,21 @@ impl Niri {
|
||||
let frame_callback_time = get_monotonic_time();
|
||||
|
||||
for win in self.layout.windows_for_output(output) {
|
||||
win.send_frame(output, frame_callback_time, None, should_send);
|
||||
win.send_frame(
|
||||
output,
|
||||
frame_callback_time,
|
||||
FRAME_CALLBACK_THROTTLE,
|
||||
should_send,
|
||||
);
|
||||
}
|
||||
|
||||
for surface in layer_map_for_output(output).layers() {
|
||||
surface.send_frame(output, frame_callback_time, None, should_send);
|
||||
surface.send_frame(
|
||||
output,
|
||||
frame_callback_time,
|
||||
FRAME_CALLBACK_THROTTLE,
|
||||
should_send,
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(surface) = &self.output_state[output].lock_surface {
|
||||
@ -2442,17 +2467,97 @@ impl Niri {
|
||||
surface.wl_surface(),
|
||||
output,
|
||||
frame_callback_time,
|
||||
None,
|
||||
FRAME_CALLBACK_THROTTLE,
|
||||
should_send,
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(surface) = &self.dnd_icon {
|
||||
send_frames_surface_tree(surface, output, frame_callback_time, None, should_send);
|
||||
send_frames_surface_tree(
|
||||
surface,
|
||||
output,
|
||||
frame_callback_time,
|
||||
FRAME_CALLBACK_THROTTLE,
|
||||
should_send,
|
||||
);
|
||||
}
|
||||
|
||||
if let CursorImageStatus::Surface(surface) = self.cursor_manager.cursor_image() {
|
||||
send_frames_surface_tree(surface, output, frame_callback_time, None, should_send);
|
||||
send_frames_surface_tree(
|
||||
surface,
|
||||
output,
|
||||
frame_callback_time,
|
||||
FRAME_CALLBACK_THROTTLE,
|
||||
should_send,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_frame_callbacks_on_fallback_timer(&self) {
|
||||
let _span = tracy_client::span!("Niri::send_frame_callbacks_on_fallback_timer");
|
||||
|
||||
// Make up a bogus output; we don't care about it here anyway, just the throttling timer.
|
||||
let output = Output::new(
|
||||
String::new(),
|
||||
PhysicalProperties {
|
||||
size: Size::from((0, 0)),
|
||||
subpixel: Subpixel::Unknown,
|
||||
make: String::new(),
|
||||
model: String::new(),
|
||||
},
|
||||
);
|
||||
let output = &output;
|
||||
|
||||
let frame_callback_time = get_monotonic_time();
|
||||
|
||||
self.layout.with_windows(|win, _| {
|
||||
win.send_frame(
|
||||
output,
|
||||
frame_callback_time,
|
||||
FRAME_CALLBACK_THROTTLE,
|
||||
|_, _| None,
|
||||
);
|
||||
});
|
||||
|
||||
for (output, state) in self.output_state.iter() {
|
||||
for surface in layer_map_for_output(output).layers() {
|
||||
surface.send_frame(
|
||||
output,
|
||||
frame_callback_time,
|
||||
FRAME_CALLBACK_THROTTLE,
|
||||
|_, _| None,
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(surface) = &state.lock_surface {
|
||||
send_frames_surface_tree(
|
||||
surface.wl_surface(),
|
||||
output,
|
||||
frame_callback_time,
|
||||
FRAME_CALLBACK_THROTTLE,
|
||||
|_, _| None,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(surface) = &self.dnd_icon {
|
||||
send_frames_surface_tree(
|
||||
surface,
|
||||
output,
|
||||
frame_callback_time,
|
||||
FRAME_CALLBACK_THROTTLE,
|
||||
|_, _| None,
|
||||
);
|
||||
}
|
||||
|
||||
if let CursorImageStatus::Surface(surface) = self.cursor_manager.cursor_image() {
|
||||
send_frames_surface_tree(
|
||||
surface,
|
||||
output,
|
||||
frame_callback_time,
|
||||
FRAME_CALLBACK_THROTTLE,
|
||||
|_, _| None,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user