mirror of
https://github.com/nestriness/nestri.git
synced 2026-11-03 22:22:39 +02:00
feat(nescope): the box's output follows the client's window size
A new input event, INPUT_OUTPUT_SIZE [4][w u16][h u16], rides the input path to nescope, which resizes its output and every window on it. The size is clamped to the launch size, so the box's encode budget holds, and kept even for 4:2:0. apply_resize existed but nothing called it. Old hubs stop a batch at an unknown type, so clients send it alone.
This commit is contained in:
@@ -338,6 +338,8 @@ pub fn decode_wire_event(data: &[u8]) -> Option<InputEvent> {
|
||||
DecodedInput::MouseWheel { dx: _dx, dy } => {
|
||||
Some(InputEvent::ScrollVertical { amount: dy as f64 })
|
||||
}
|
||||
// Not input: the IPC source hands it to the output before this.
|
||||
DecodedInput::OutputSize { .. } => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -404,7 +404,11 @@ fn main() {
|
||||
}
|
||||
loop_handle
|
||||
.insert_source(source, move |payload, _, data| {
|
||||
if let Some(event) = decode_wire_event(&payload) {
|
||||
if let Some(nesprotocol::input::DecodedInput::OutputSize { width, height }) =
|
||||
nesprotocol::input::decode_input_event(&payload)
|
||||
{
|
||||
data.state.request_output_size(width, height);
|
||||
} else if let Some(event) = decode_wire_event(&payload) {
|
||||
process_input(event, &mut data.state);
|
||||
}
|
||||
})
|
||||
|
||||
@@ -59,6 +59,10 @@ use crate::input::InputEvent;
|
||||
// CalloopData — threaded through the event loop
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// The smallest side a client's window can make the output. Below it, games
|
||||
/// lay out menus they cannot fit, and nothing is gained.
|
||||
const MIN_OUTPUT: u32 = 320;
|
||||
|
||||
pub struct CalloopData {
|
||||
pub state: NescopeState,
|
||||
pub display: Display<NescopeState>,
|
||||
@@ -195,6 +199,10 @@ pub struct NescopeState {
|
||||
// ── Dimensions + frame rate ───────────────────────────────────────────
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
/// The size the box was started at, which is what its encode budget was
|
||||
/// counted for, ref(d-0036): a client's window can shrink the output
|
||||
/// below it, never grow it past.
|
||||
pub launch_size: (u32, u32),
|
||||
pub fps: u32,
|
||||
|
||||
// ── Lifecycle ─────────────────────────────────────────────────────────
|
||||
@@ -328,6 +336,7 @@ impl NescopeState {
|
||||
presentation_seq: 0,
|
||||
width,
|
||||
height,
|
||||
launch_size: (width, height),
|
||||
fps,
|
||||
loop_handle,
|
||||
game_launched: false,
|
||||
@@ -462,8 +471,17 @@ impl NescopeState {
|
||||
// Resize
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/// The client's window is `width`x`height`: follow it, inside the launch
|
||||
/// size and on even numbers, which every encoder needs for 4:2:0.
|
||||
pub fn request_output_size(&mut self, width: u16, height: u16) {
|
||||
let fit = |want: u16, max: u32| (u32::from(want).clamp(MIN_OUTPUT, max) & !1).max(2);
|
||||
let (w, h) = (fit(width, self.launch_size.0), fit(height, self.launch_size.1));
|
||||
if (w, h) != (self.width, self.height) {
|
||||
self.apply_resize(w, h);
|
||||
}
|
||||
}
|
||||
|
||||
/// Apply a new output resolution (e.g. from a runtime resize request).
|
||||
#[allow(unused)]
|
||||
pub fn apply_resize(&mut self, width: u32, height: u32) {
|
||||
tracing::info!("Applying resize: {width}x{height}");
|
||||
self.width = width;
|
||||
|
||||
@@ -6,7 +6,9 @@ use tokio::sync::Mutex;
|
||||
use tracing::{debug, info, warn};
|
||||
|
||||
use nesprotocol::datagram::{DGRAM_AUDIO, DGRAM_BUFFER_BYTES, DGRAM_VIDEO};
|
||||
use nesprotocol::input::{INPUT_KEY, INPUT_MOUSE_BUTTON, INPUT_MOUSE_MOVE, INPUT_MOUSE_WHEEL};
|
||||
use nesprotocol::input::{
|
||||
INPUT_KEY, INPUT_MOUSE_BUTTON, INPUT_MOUSE_MOVE, INPUT_MOUSE_WHEEL, INPUT_OUTPUT_SIZE,
|
||||
};
|
||||
use nesprotocol::{BIDI_CONTROL, BIDI_INPUT, Carrier, STREAM_CURSOR, STREAM_STATS};
|
||||
use nesprotocol::{ControlMode, ReceiverReport, decode_control_mode, decode_receiver_report};
|
||||
use nesprotocol::{FRAME_HDR_LEN, STREAM_VERSION, encode_frame};
|
||||
@@ -521,8 +523,8 @@ fn split_input_events(payload: &[u8]) -> Vec<Vec<u8>> {
|
||||
let len = match payload[offset] {
|
||||
// [type][up/down][keycode u16 LE]
|
||||
INPUT_KEY => 4,
|
||||
// [type][dx i16 LE][dy i16 LE]
|
||||
INPUT_MOUSE_MOVE | INPUT_MOUSE_WHEEL => 5,
|
||||
// [type][dx i16 LE][dy i16 LE], and [type][w u16 LE][h u16 LE]
|
||||
INPUT_MOUSE_MOVE | INPUT_MOUSE_WHEEL | INPUT_OUTPUT_SIZE => 5,
|
||||
// [type][button][up/down]
|
||||
INPUT_MOUSE_BUTTON => 3,
|
||||
other => {
|
||||
|
||||
Reference in New Issue
Block a user