窗口拖动区域 Builder

窗口拖动 Builder 用来把一个控件声明为系统窗口拖动区域。它主要用于无边框窗口:用户按住这个区域拖动时,Flor 会调用平台层的 drag_window(),让系统接管窗口移动。

基本用法

导入 WindowDragBuilder 后,所有实现 ViewIdentity 的控件都可以调用 .window_drag_area()

use flor::view::builder::WindowDragBuilder;
use flor::views;
use flor::windows::WindowOption;
use flor_lys::div::div;
use flor_lys::label::label;

WindowOption {
    borderless: true,
    ..WindowOption::default()
}
.open(|_| {
    div(views![label("拖动这里移动窗口")])
        .window_drag_area()
})?;

.window_drag_area() 等价于把当前控件的拖动策略设为 WindowDragPolicy::Allow

动态策略

如果拖动能力需要随状态变化,可以使用 .window_drag_policy(...)

use flor::view::builder::WindowDragBuilder;
use flor::view::WindowDragPolicy;

let title_bar = title_bar.window_drag_policy(move || {
    if dragging_enabled.get() {
        WindowDragPolicy::Allow
    } else {
        WindowDragPolicy::Deny
    }
});

策略闭包会被响应式更新器重新求值,结果写入运行时存储。

策略含义

策略含义
WindowDragPolicy::Allow当前控件允许触发系统窗口拖动。
WindowDragPolicy::Deny当前控件禁止触发系统窗口拖动。
WindowDragPolicy::Inherit当前控件不做决定,继续向父控件查找策略。

默认策略是 Deny。命中测试得到的控件会从自身开始向父级查找策略;遇到 Deny 会停止并禁止拖动,遇到 Allow 会调用控件的 on_window_drag_hit_test(...) 做最后判断。

和事件的关系

窗口拖动只在没有鼠标捕获时生效。左键按下后,如果命中控件允许拖动,Flor 会直接触发系统拖动并返回,不再继续派发这个按下事件给控件。

如果某个控件内部只有一部分区域可拖动,控件作者可以覆盖 View::on_window_drag_hit_test(mouse_position)。传入坐标是当前控件局部坐标,默认返回 true

如果控件需要默认表达自己的拖动策略,可以覆盖 View::on_window_drag_policy();应用侧通过 Builder 设置的策略优先级更高。