簡體   English   中英

cairo / xlib不更新窗口內容

[英]cairo / xlib not updating window content

我正在嘗試學習如何在xlib曲面上使用Cairo 2D圖形庫

我寫了一個小測試程序,可以創建多個窗口。 每個函數都有一個自定義的paint()函數,該函數會定期調用以向窗口添加一些圖形內容,或者根據需要完全重繪它。 還有一個選項可以定義鼠標和按鍵偵聽器。 主例程檢查X事件(將它們委派給鼠標和按鍵偵聽器),以及檢查是否定期超時調用這些paint()函數。

我嘗試使用1.14.6版本的Cairo(當前可在Ubuntu 16.04中作為軟件包使用)和最新的1.15.12,但是結果是相同的。

該演示的預期行為是打開3個窗口。 一個將添加隨機矩形,另一個將添加隨機文本,第三個將添加隨機圓。

此外,單擊窗口應產生線條(連接到鼠標單擊或隨機單擊),並且使用箭頭鍵應在窗口中用圓圈繪制一條紅線。

圓圈和文字似乎按預期規律顯示。 所有三個窗口都應具有白色背景,但其中兩個是黑色。 最糟糕的是,帶有矩形的窗口更新得並不多(無論是否創建了第一個窗口,它始終不會正確顯示矩形)。

僅在焦點切換到該窗口或從該窗口切換焦點時才顯示它們-然后本應繪制的其余矩形突然出現。

添加任何內容后,我在每個窗口的表面上調用cairo_surface_flush(),但這無濟於事。 我還嘗試過將XEvents發布到各種類型的窗口(例如焦點),它們到達了,但是矩形沒有顯示出來。

此外,即使使用鼠標繪制線條效果很好,但帶有鍵箭頭的繪制線條也會遇到相同的問題-已繪制但未正確顯示。

我對這個庫可以做什么的某些假設顯然是錯誤的,但是我不確定在哪里。

似乎顯示了兩個相互競爭的圖形版本,因為有時會出現一個或兩個矩形或紅線閃爍的情況。 某種奇怪的緩沖,緩存? 我不知道這可能只是我程序中的一些錯誤。

另一個觀察結果-黑色背景是因為繪制白色背景發生在顯示窗口之前,因此以某種方式丟棄了這些cairo_paint調用。 我不知道如何使窗口更早出現,似乎僅在稍后在屏幕上進行更改后才出現。

經過幾天的絕望,我被困在了這里,請您幫我至少一部分幫助嗎?

該程序在這里: test_cairo.c

屏幕截圖示例(按鍵繪制的紅色虛線和矩形無法正確顯示): test_cairo.png

進行編譯(在Ubuntu 16.04或類似系統上):

gcc -o test_cairo test_cairo.c -I/usr/include/cairo -lX11 -lcairo 

X11不會為您保留窗口內容。 當您獲得Expose事件時,您必須完全重繪該事件描述的區域。

所有三個窗口都應具有白色背景,但其中兩個是黑色。

您使用XCreateSimpleWindow創建窗口,因此它們的background屬性設置為black。 X11服務器將在發送暴露事件之前為您填充黑色的暴露區域。 由於您不告訴開羅繪制白色背景,因此黑色保持不變。

嘗試這個:

--- test_cairo.c.orig   2018-07-28 09:53:10.000000000 +0200
+++ test_cairo.c    2018-07-29 10:52:43.268867754 +0200
@@ -63,6 +63,7 @@ static gui_mouse_callback mouse_callback

 static cairo_t *windows[MAX_GUI_WINDOWS_COUNT];
 static cairo_surface_t *surfaces[MAX_GUI_WINDOWS_COUNT];
+static cairo_surface_t *real_surfaces[MAX_GUI_WINDOWS_COUNT];
 static Window x11windows[MAX_GUI_WINDOWS_COUNT];
 static char *window_names[MAX_GUI_WINDOWS_COUNT];

@@ -79,7 +80,12 @@ long long usec()
 void repaint_window(int window_handle)
 {
     draw_callbacks[window_handle](windows[window_handle]);
-    cairo_surface_flush(surfaces[window_handle]);     
+
+    cairo_t *cr = cairo_create(real_surfaces[window_handle]);
+    cairo_set_source_surface(cr, surfaces[window_handle], 0, 0);
+    cairo_paint(cr);
+    cairo_destroy(cr);
+    cairo_surface_flush(real_surfaces[window_handle]);     
 }

 int gui_cairo_check_event(int *xclick, int *yclick, int *win)
@@ -149,7 +155,6 @@ void draw_windows_title(int window_handl
        sprintf(fullname, "Mikes - %d - [%s]", window_handle, context_names[current_context]);    
     else 
        sprintf(fullname, "Mikes - %s - [%s]", window_names[window_handle], context_names[current_context]);
-    cairo_surface_flush(surfaces[window_handle]);  
     XStoreName(dsp, x11windows[window_handle], fullname);
 }

@@ -179,20 +184,17 @@ int gui_open_window(gui_draw_callback pa
         }
     if (window_handle < 0) return -1;

-    surfaces[window_handle] = gui_cairo_create_x11_surface(&width, &height, window_handle);
+    real_surfaces[window_handle] = gui_cairo_create_x11_surface(&width, &height, window_handle);
+    surfaces[window_handle] = cairo_surface_create_similar(real_surfaces[window_handle], CAIRO_CONTENT_COLOR, width, height);
     windows[window_handle] = cairo_create(surfaces[window_handle]);

     mouse_callbacks[window_handle] = 0;
     draw_callbacks[window_handle] = paint;    
     window_update_periods[window_handle] = update_period_in_ms;
     window_names[window_handle] = 0;
-
-    cairo_surface_flush(surfaces[window_handle]);     

     cairo_set_source_rgb(windows[window_handle], 1, 1, 1);
     cairo_paint(windows[window_handle]);
-
-    cairo_surface_flush(surfaces[window_handle]);     

     draw_callbacks[window_handle](windows[window_handle]);

@@ -201,7 +203,6 @@ int gui_open_window(gui_draw_callback pa
     else next_window_update[window_handle] = 0;

     draw_windows_title(window_handle);
-    cairo_surface_flush(surfaces[window_handle]);     
     window_in_use[window_handle] = 1;

     return window_handle;
@@ -213,6 +214,7 @@ void gui_close_window(int window_handle)

     cairo_destroy(windows[window_handle]);
     cairo_surface_destroy(surfaces[window_handle]);
+    cairo_surface_destroy(real_surfaces[window_handle]);
     window_in_use[window_handle] = 0;
     int no_more_windows = 1;
     for (int i = 0; i < MAX_GUI_WINDOWS_COUNT; i++)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM