dotnet C# 建立 X11 應用時設定視窗背景顏色

lindexi發表於2024-06-01

本文將告訴大家如何在 X11 裡面建立一個視窗時,設定視窗的背景顏色

dotnet C# 設定 X11 應用視窗背景透明 的基礎上,可以透過建立 XColor 結構體,將 XColor 賦值給到 XSetWindowAttributes 的 background_pixel 進行設定視窗的初始化背景顏色

核心實現如下

先建立 XColor 結構體,程式碼如下

XColor color = new XColor()
{
    red = 0xF556, // value is 0-65535
    green = 0xC156,
    blue = 0x2156,
    flags = (byte)(ColorFlags.DoRed | ColorFlags.DoGreen | ColorFlags.DoBlue),
};

以上的 XColor 的三個顏色分量是 0-65535 範圍的,即 0-0xFFFF 範圍,而不是常見的 WPF 系的 0-0xFF 範圍。換句話說如果你在 XColor 裡面使用 WPF 系習慣的寫法,將會發現最終顏色都是一個黑色

最後一個引數(欄位)用來指明有哪些顏色分量是有效的。以上的 XColor 和 ColorFlags 型別定義都是從 CPF 和 Avalonia 裡面複製的,可以從本文末尾找到所有的程式碼的下載方法

完成 XColor 建立之後,再需要使用 XCreateColormap 建立顏色對映表,程式碼如下

var colormap = XCreateColormap(display, rootWindow, visual, 0);

以上程式碼的 display 和 visual 等引數的獲取程式碼如下

var display = XOpenDisplay(IntPtr.Zero);
var screen = XDefaultScreen(display);

var rootWindow = XDefaultRootWindow(display);

var result = XMatchVisualInfo(display, screen, 32, 4, out var info);

獲取到所建立顏色對映表之後,即可透過 XAllocColor 獲取對應的顏色了。為什麼需要這一步?這是因為在X11裡面支援多個不同的格式的顏色,需要經過這一步驟才能獲取具體裝置相關的顏色。雖然大多數時候都是咱熟悉的 RGB 的 0xAARRGGBB 格式

XAllocColor(display, colormap, ref color);

Console.WriteLine(color.pixel.ToString("X"));

接著將 XColor 的 pixel 欄位賦值給到 XSetWindowAttributes 的 background_pixel 欄位,程式碼如下

var xSetWindowAttributes = new XSetWindowAttributes
{
    backing_store = 1,
    bit_gravity = Gravity.NorthWestGravity,
    win_gravity = Gravity.NorthWestGravity,
    //override_redirect = true, // 設定視窗的override_redirect屬性為True,以避免視窗管理器的干預
    colormap = colormap,
    border_pixel = 0,
    background_pixel = color.pixel,
};

如此執行建立視窗時,即可使用所配置的顏色。所有的程式碼如下

using static CPF.Linux.XLib;
var display = XOpenDisplay(IntPtr.Zero);
var screen = XDefaultScreen(display);

var rootWindow = XDefaultRootWindow(display);

var result = XMatchVisualInfo(display, screen, 32, 4, out var info);
Console.WriteLine($"Result={result} info.depth={info.depth}");

var visual = info.visual;

var valueMask =
        //SetWindowValuemask.BackPixmap
        0
        | SetWindowValuemask.BackPixel
        | SetWindowValuemask.BorderPixel
        | SetWindowValuemask.BitGravity
        | SetWindowValuemask.WinGravity
        | SetWindowValuemask.BackingStore
        | SetWindowValuemask.ColorMap
    //| SetWindowValuemask.OverrideRedirect
    ;


var colormap = XCreateColormap(display, rootWindow, visual, 0);

XColor color = new XColor()
{
    red = 0xF556, // value is 0-65535
    green = 0xC156,
    blue = 0x2156,
    flags = (byte)(ColorFlags.DoRed | ColorFlags.DoGreen | ColorFlags.DoBlue),
};

XAllocColor(display, colormap, ref color);

Console.WriteLine(color.pixel.ToString("X"));

var xSetWindowAttributes = new XSetWindowAttributes
{
    backing_store = 1,
    bit_gravity = Gravity.NorthWestGravity,
    win_gravity = Gravity.NorthWestGravity,
    //override_redirect = true, // 設定視窗的override_redirect屬性為True,以避免視窗管理器的干預
    colormap = colormap,
    border_pixel = 0,
    background_pixel = color.pixel,
};

var width = 500;
var height = 500;
var handle = XCreateWindow(display, rootWindow, 0, 0, width, height, 5,
    (int) info.depth,
    (int) CreateWindowArgs.InputOutput,
    visual,
    (nuint) valueMask, ref xSetWindowAttributes);

XMapWindow(display, handle);
XFlush(display);

while (true)
{
    var xNextEvent = XNextEvent(display, out var @event);
    if (xNextEvent != 0)
    {
        break;
    }
}

本文程式碼放在 githubgitee 上,可以使用如下命令列拉取程式碼

先建立一個空資料夾,接著使用命令列 cd 命令進入此空資料夾,在命令列裡面輸入以下程式碼,即可獲取到本文的程式碼

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 2ff0f8d8c502761d58179fa77c3928c7586ae75f

以上使用的是 gitee 的源,如果 gitee 不能訪問,請替換為 github 的源。請在命令列繼續輸入以下程式碼,將 gitee 源換成 github 源進行拉取程式碼

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 2ff0f8d8c502761d58179fa77c3928c7586ae75f

獲取程式碼之後,進入 X11/YalcharlellawWaylarwejear 資料夾,即可獲取到原始碼

更多 X11 開發請參閱 部落格導航

相關文章