gtk:当应用程序失去焦点时如何隐藏窗口

发布于 2024-08-11 21:47:31 字数 2226 浏览 4 评论 0原文

我想复制 OpenOffice 中工具窗口的行为。当应用程序失去焦点时,工具窗口(如果它们未停靠)将被隐藏。

因此,我有一个主窗口和另一个实用程序窗口 (win_dock)。我想在应用程序的所有窗口失去焦点时隐藏 win_dock ,并在窗口获得焦点时再次显示它。

我所做的是连接到应用程序所有窗口的焦点事件和焦点事件,并维护一个计数器来记录有多少个窗口具有焦点。当这个计数器降到零时,我想隐藏 win_dock,如果这个计数器再次为正,我想显示 win_dock

问题是这个解决方案我永远无法集中注意力win_dock。因为当我点击它时,主窗口会失去焦点,因此它隐藏了仍未获得焦点的 win_dock 。尽管如此,事件焦点仍会发送到 win_dock 并且窗口会重新出现。但与此同时,它已经失去了焦点。

您有更好的解决方案吗?

这是 Vala 源代码:

public class Main
{

  private Gtk.Builder builder;
  private Gtk.Window  win_messages;
  private Gtk.Window  win_dock;
  private int focus_count = 0;

  public Main() {
    builder = new Gtk.Builder();
    builder.add_from_file("ui2.glade");
    win_messages = builder.get_object("win_messages") as Gtk.Window;
    win_dock     = builder.get_object("win_dock")     as Gtk.Window;
    handle_focus(win_messages);
    handle_focus(win_dock);
  }

  public void start(){
    win_messages.show_all();    
    //win_dock.show_all();
    Gtk.main();
  }

  private void handle_focus(Gtk.Window w) {
    w.focus_in_event.connect ((w, e) => {
      stdout.printf("Focus In  (%s)\n", w.name);
      focus_count++;
      manage_focus(w == win_dock);
    });
    w.focus_out_event.connect((w, e) => {
      stdout.printf("Focus Out (%s)\n", w.name);
      focus_count--;
      manage_focus(w == win_dock);
    });
  }

  private void manage_focus(bool is_dock){
    if(focus_count > 0) {
      win_dock.show_all();
      stdout.printf("Show (focus: %d)\n", focus_count);
    } else if(is_dock) {
      win_dock.hide_all();
      stdout.printf("Hide (focus: %d, has: %d) dock\n", focus_count, win_dock.is_active ? 1 : 0);
    } else if(!is_dock) {
      if(win_dock.is_active) {
        win_dock.hide_all();
        stdout.printf("Hide (focus: %d, has: %d) !dock\n", focus_count, win_dock.is_active ? 1 : 0);
      } else {
        stdout.printf("Nop  (focus: %d, has: %d) !dock\n", focus_count, win_dock.is_active ? 1 : 0);
      }
    }
  }

  public static int main (string[] args)
  {
    Gtk.init (ref args);
    Main m = new Main();
    m.start();

    return 0;
  }
}

谢谢。

I want to duplicate the behaviour of tool windows in OpenOfice. When the application loses focus, the tool windows (if they are not docked) are hidden.

So, I have a main window, and another utility window (win_dock). I want to hide win_dock when all the windows of the application loses focus and show it again if a window gain focus.

What I did is that I connected to the focus-in-event and focus-out-event of all windows of the application, and I maintain a counter of how many windows have focus. When this counter drops to zero, I want to hide win_dock, and if this counter is positive again, I want to show win_dock

The problem is with this solution I can never focus win_dock. Because when I click on it, the main window drops the focus, so it hides win_dock that still hadn't gained the focus. Nevertheless the focus-in-event is still sent to win_dock and the windows reappears. But in the meantime it has lost the focus.

Do you have a better solution?

Here is the Vala source code:

public class Main
{

  private Gtk.Builder builder;
  private Gtk.Window  win_messages;
  private Gtk.Window  win_dock;
  private int focus_count = 0;

  public Main() {
    builder = new Gtk.Builder();
    builder.add_from_file("ui2.glade");
    win_messages = builder.get_object("win_messages") as Gtk.Window;
    win_dock     = builder.get_object("win_dock")     as Gtk.Window;
    handle_focus(win_messages);
    handle_focus(win_dock);
  }

  public void start(){
    win_messages.show_all();    
    //win_dock.show_all();
    Gtk.main();
  }

  private void handle_focus(Gtk.Window w) {
    w.focus_in_event.connect ((w, e) => {
      stdout.printf("Focus In  (%s)\n", w.name);
      focus_count++;
      manage_focus(w == win_dock);
    });
    w.focus_out_event.connect((w, e) => {
      stdout.printf("Focus Out (%s)\n", w.name);
      focus_count--;
      manage_focus(w == win_dock);
    });
  }

  private void manage_focus(bool is_dock){
    if(focus_count > 0) {
      win_dock.show_all();
      stdout.printf("Show (focus: %d)\n", focus_count);
    } else if(is_dock) {
      win_dock.hide_all();
      stdout.printf("Hide (focus: %d, has: %d) dock\n", focus_count, win_dock.is_active ? 1 : 0);
    } else if(!is_dock) {
      if(win_dock.is_active) {
        win_dock.hide_all();
        stdout.printf("Hide (focus: %d, has: %d) !dock\n", focus_count, win_dock.is_active ? 1 : 0);
      } else {
        stdout.printf("Nop  (focus: %d, has: %d) !dock\n", focus_count, win_dock.is_active ? 1 : 0);
      }
    }
  }

  public static int main (string[] args)
  {
    Gtk.init (ref args);
    Main m = new Main();
    m.start();

    return 0;
  }
}

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

看海 2024-08-18 21:47:31

有充分的理由让对话框消失吗?使 win_dock 瞬时(win_dock.set_transient_for) 用于主窗口?

否则你可以尝试使用 GLib.Idle.add 调用manage_focus这将导致
manage_focus 在所有焦点事件回调运行后运行。然后它将具有正确数量的聚焦窗口。

Is there a good reason to make the dialog disappear? Wouldn't it be enough to make win_dock transient (win_dock.set_transient_for) for the main window?

Otherwise you could try using GLib.Idle.add to call manage_focuswhich will cause
manage_focus to run after all your focus event callbacks have run. It will then have the correct number of focused windows.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文