You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中如何重置等待/睡眠时间?适配OSD弹窗按键场景

解决EWW OSD弹窗的延迟关闭与计时器重置问题

核心思路

绝对不能用阻塞式的sleep(),否则会卡死整个按键监听逻辑。必须依赖异步定时器结合程序的事件循环实现延迟关闭,同时通过维护定时器句柄,实现多次按键时的计时器重置。


问题1:实现非阻塞延迟关闭弹窗

使用程序框架提供的异步定时器API(比如GLib的timeout_add、Rust的事件循环定时器、Python的GLib定时器),将关闭弹窗的任务加入事件队列,等待N毫秒后执行,完全不会阻塞当前的按键监听流程。

问题2:弹窗关闭前多次按键重置计时器

需要保存当前活跃的定时器句柄(ID/引用),每次触发按键时:

  1. 若存在未触发的旧定时器,先取消它;
  2. 重新启动一个新的N毫秒定时器;
  3. 调用osd_open确保弹窗处于打开状态(EWW的widget重复打开通常不会产生多窗口)。

代码示例(Rust + GLib)

假设程序基于GLib事件循环(Linux桌面应用常用):

// 在全局或结构体中维护定时器句柄
let mut vol_osd_timer: Option<glib::SourceId> = None;

if event.event_type == KeyPress(VOL_DN) {
    // 打开音量OSD弹窗
    osd_open("osd-vol");

    // 取消之前未触发的定时器
    if let Some(timer_id) = vol_osd_timer.take() {
        glib::source_remove(timer_id);
    }

    // 启动新的异步定时器,N毫秒后关闭弹窗
    vol_osd_timer = Some(glib::timeout_add_local(
        std::time::Duration::from_millis(N),
        move || {
            osd_close("osd-vol");
            // 返回Break表示定时器仅执行一次
            glib::ControlFlow::Break
        },
    ));
}

代码示例(Python + PyGObject)

import gi
gi.require_version('GLib', '2.0')
from gi.repository import GLib

# 全局变量保存定时器ID
vol_osd_timer = None

def handle_volume_down(event):
    global vol_osd_timer
    # 打开OSD弹窗
    osd_open("osd-vol")

    # 取消旧定时器
    if vol_osd_timer is not None:
        GLib.source_remove(vol_osd_timer)
        vol_osd_timer = None

    # 定义延迟关闭的回调函数
    def close_osd():
        osd_close("osd-vol")
        return False  # 仅执行一次

    # 启动新定时器(N为毫秒数)
    vol_osd_timer = GLib.timeout_add(N, close_osd)

关键注意事项

  • 优先使用与主事件循环集成的异步定时器,避免手动创建线程(线程会增加复杂度,易引发竞态问题);
  • 确认osd_open重复调用不会产生多窗口(EWW默认支持单实例widget,重复执行eww open不会重复创建);
  • 若使用其他框架(比如Qt的QTimer),核心逻辑一致:维护定时器实例,每次按键时停止旧定时器并启动新的。

内容的提问来源于stack exchange,提问作者candifloss__

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 21:54:54