WindowRequestApi

WindowRequestApi is the deferred window command interface in flor::windows. It provides a set of request_* methods for WindowId, enqueuing window operations into Flor's event loop queue rather than directly calling platform window APIs on the current call stack.

use flor::windows::WindowRequestApi;

window_id.request_set_size((1024, 768));

Design Purpose

request_* methods exist to avoid window operations re-entering the platform layer at the wrong time.

Typical risks include:

  • Modifying a window directly during window message processing, causing platform message re-entry.
  • Directly calling set_size / destroy during reactive updates, layout refresh or drawing, causing nested event loop execution.
  • Cross-thread callbacks directly controlling windows, leading to UI thread restrictions, ordering issues, deadlocks or infinite loops.

WindowRequestApi defers operations to a unified flush point in Flor's event loop: first finish the current dispatch, then execute enqueued window commands in FIFO order.

Trait

pub trait WindowRequestApi {
    fn request_update_window(self) -> WindowCommandRequest;
    fn request_show(self) -> WindowCommandRequest;
    fn request_hide(self) -> WindowCommandRequest;
    fn request_set_window_mode(self, mode: WindowMode) -> WindowCommandRequest;
    fn request_set_left(self, left: i32) -> WindowCommandRequest;
    fn request_set_top(self, top: i32) -> WindowCommandRequest;
    fn request_set_position(self, pos: (i32, i32)) -> WindowCommandRequest;
    fn request_set_width(self, width: u32) -> WindowCommandRequest;
    fn request_set_height(self, height: u32) -> WindowCommandRequest;
    fn request_set_size(self, size: (u32, u32)) -> WindowCommandRequest;
    fn request_destroy(self) -> WindowCommandRequest;
    fn request_drag_window(self) -> WindowCommandRequest;
}

The current implementation implements this trait for WindowId.

Command Reference

MethodPurposeCorresponding Sync API
request_update_window()Request synchronous window update.update_window()
request_show()Show the window.show()
request_hide()Hide the window.hide()
request_set_window_mode(mode)Set the window mode.set_window_mode(mode)
request_set_left(left)Set the window left coordinate.set_left(left)
request_set_top(top)Set the window top coordinate.set_top(top)
request_set_position((x, y))Set the window position.set_position((x, y))
request_set_width(width)Set the window width.set_width(width)
request_set_height(height)Set the window height.set_height(height)
request_set_size((width, height))Set the window size.set_size((width, height))
request_destroy()Destroy the window.destroy()
request_drag_window()Trigger system window drag.drag_window()

Return Value

All request_* methods return WindowCommandRequest:

pub struct WindowCommandRequest {
    // Internal command ID
}

It is used to attach an execution result callback to the enqueued command:

window_id.request_show().result(|result| {
    if let Err(err) = result {
        eprintln!("show failed: {err}");
    }
});

The callback type is:

impl FnOnce(Result<(), Error>) + Send + 'static

The callback is invoked after flush_window_commands() executes the command, not immediately from within result(...).

Timing of result

WindowCommandRequest is a single-use handle. When you need the result, call .result(...) immediately after creating the request:

window_id
    .request_set_size((800, 600))
    .result(|result| {
        if let Err(err) = result {
            eprintln!("resize failed: {err}");
        }
    });

Don't save the request first and attach the callback much later. The event loop may have already executed and removed the command; if the callback is registered after command execution, Flor will invoke the callback with an error result.

If you don't care about the result, you can simply discard the return value:

window_id.request_destroy();

Cross-thread Behavior

The request_* methods themselves are always available. Whether cross-thread-window-commands is enabled affects the event loop wake-up behavior after cross-thread submission.

featureBehavior
cross-thread-window-commands not enabledCommands are still enqueued, but the event loop waits until it naturally wakes up to process them.
cross-thread-window-commands enabledAfter commands are enqueued, the event loop wake-up capability is invoked to let the event loop thread flush commands as soon as possible.

cross-thread-window-commands automatically enables event-loop-wakeup. For complete usage scenarios, see Cross-thread Window Commands.

Execution Order

Commands are executed in FIFO order. flush_window_commands() only processes the current batch each time: newly added commands during execution are left for subsequent batches, avoiding recursive commands continuously expanding the current flush.

After execution completes, if commands have result(...) callbacks attached, Flor enqueues the callbacks into a completion queue and invokes them together.