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

gtk-rs中如何在窗口显示后触发代码?无需sleep实现窗口调整

解决gtk-rs窗口显示后触发代码的问题

可行方案

  • 使用connect_map信号替代connect_show:
    connect_map会在窗口**真正被映射到屏幕(完成渲染显示)**后触发,而非connect_show那样在调用show()前执行。修改代码中的信号连接部分:

    window.connect_map(|window| {
        println!("3");
        // 在这里执行窗口位置大小调整的命令或逻辑
        let output = Command::new("wmctrl")
            .args(["-r", "CSS", "-e", "1,640,100,680,768"])
            .output()
            .expect("failed to execute process");
        println!("{:?}", output);
    });
    
  • 利用glib::idle_add延迟执行:
    如果需要确保在主循环完成当前渲染任务后执行,可以将调整逻辑放到空闲回调中,它会在GTK主循环处理完所有待处理事件后运行:

    window.connect_show(|window| {
        println!("2");
        glib::idle_add_local(move || {
            println!("3");
            let output = Command::new("wmctrl")
                .args(["-r", "CSS", "-e", "1,640,100,680,768"])
                .output()
                .expect("failed to execute process");
            println!("{:?}", output);
            glib::ControlFlow::Break
        });
    });
    
  • 监听窗口的mapped属性变化:
    通过监听GdkWindow的mapped属性,确认窗口已被映射后执行逻辑:

    if let Some(gdk_window) = window.window() {
        gdk_window.connect_notify_local("mapped", |gdk_window, _| {
            if gdk_window.is_mapped() {
                println!("3");
                let output = Command::new("wmctrl")
                    .args(["-r", "CSS", "-e", "1,640,100,680,768"])
                    .output()
                    .expect("failed to execute process");
                println!("{:?}", output);
            }
        });
    }
    

原理说明

connect_show的触发时机是窗口的visible属性被设置为true时,此时窗口还未完成与窗口系统的映射、渲染到屏幕的操作。而connect_map、mapped属性变化或idle_add的回调,都会等待窗口真正完成屏幕渲染后才执行,因此无需额外添加sleep即可让wmctrl命令生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 10:15:35