2013-10-16 33 views
1

我有一個用C編寫的小例子程序,它使用XCB API打開一個窗口。XCB:窗口在映射一次後不會取消映射

嚴格AFTER我已經創建和所示的窗口,我會(在以後的時間)要隱藏的窗口。 (很明顯,在這個特定的例子中,我可以刪除對xcb_map_window的調用,並且該窗口將被隱藏,但是我想在稍後的大型應用程序中執行此操作,就像切換顯示/隱藏窗口一樣,注意:我不想將它最小化)。

下面是示例代碼(注意:此代碼現在工作多虧了答案):

#include <unistd.h> 
#include <stdio.h> 
#include <stdbool.h> 
#include <xcb/xcb.h> 

void set_window_visible(xcb_connection_t* c, xcb_window_t win, bool visible) { 
    xcb_generic_event_t *event; 

    if(visible) { 
     // Map the window on the screen 
     xcb_map_window (c, win); 

     // Make sure the map window command is sent 
     xcb_flush(c); 

     // Wait for EXPOSE event. 
     // 
     // TODO: add timeout in-case X server does not ever send the expose event. 
     while(event = xcb_wait_for_event(c)) { 
      bool gotExpose = false; 

      switch(event->response_type & ~0x80) { 
      case XCB_EXPOSE: 
       gotExpose = true; 
       break; 

      default: 
       break; // We don't know the event type, then. 
      } 
      free(event); 

      if(gotExpose) { 
       break; 
      } 
     } 

    } else { 
     // Hide the window 
     xcb_unmap_window(c, win); 

     // Make sure the unmap window command is sent 
     xcb_flush(c); 
    } 
} 

int main() { 
    xcb_connection_t *c; 
    xcb_screen_t  *screen; 
    xcb_window_t  win; 
    xcb_generic_event_t *event; 

    // Open the connection to the X server 
    c = xcb_connect (NULL, NULL); 

    // Get the first screen 
    screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data; 

    // Ask for our window's Id 
    win = xcb_generate_id(c); 

    // Create the window 
    uint32_t mask = XCB_CW_EVENT_MASK; 
    uint32_t valwin[] = {XCB_EVENT_MASK_EXPOSURE | XCB_BUTTON_PRESS}; 
    xcb_create_window(
     c,        // Connection 
     XCB_COPY_FROM_PARENT,   // depth (same as root) 
     win,       // window Id 
     screen->root,     // parent window 
     0, 0,       // x, y 
     150, 150,      // width, height 
     10,       // border_width 
     XCB_WINDOW_CLASS_INPUT_OUTPUT, // class 
     screen->root_visual,   // visual 
     mask, valwin     // masks 
    ); 

    bool visible = true; 
    set_window_visible(c, win, true); 

    while(1) { 
     sleep(2); 

     // Toggle visibility 
     visible = !visible; 
     set_window_visible(c, win, visible); 

     printf("Window visible: "); 
     if(visible) { 
      printf("true.\n"); 
     } else { 
      printf("false.\n"); 
     } 
    } 

    // pause until Ctrl-C 
    pause(); 
    return 0; 
} 

其中我編譯和運行:

gcc xcbwindow.c -o xcbwindow -lxcb 
./xcbwindow 

從什麼我可以找到關於谷歌或在這裏,我正在做的一切正確。所以澄清我使用的團結和Ubuntu 12.04 LTS:

統一--version報告:

unity 5.20.0 

UNAME -a報告:

Linux [redacted] 3.2.0-32-generiC#51-Ubuntu SMP Wed Sep 26 21:33:09 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux 

任何人都可以解釋,我已經走了錯在這個代碼中?編輯:在xcb_unmap_window()後面用flush()更新後的代碼;仍然不起作用。

EDIT2:用肉桂WM試過的代碼;仍然不起作用(這不是一個統一的錯誤)。

EDIT3:本文中更新的代碼現在可用。

回答

2

你的程序太簡單了。

它映射窗口,然後立即取消映射它。窗口是頂層,這意味着請求被重定向到窗口管理器。但窗口管理器在窗口尚未映射時仍然收到未映射請求,因此它只是放棄請求。在地圖和未映射呼叫之間插入sleep(3)並觀察。

在實際代碼中,您的窗口在發送取消映射請求之前至少需要一次公開事件。這保證它實際上由窗口管理器映射。

+0

謝謝你的提示!這確實解決了這個問題。我會用適當的工作代碼更新我的問題。你知道我是否會遇到類似這樣的奇怪怪癖嗎?例如。是揭露相反的事件嗎? – powerpup118