本文将告诉大家如何在 dotnet 里面的后台线程设置 X11 窗口的最小化

核心设置 X11 窗口最小化的方法是 XIconifyWindow 方法,核心问题是在后台线程需要自己使用 XOpenDisplay 获取 Display 对象,且必须调用 XCloseDisplay 时才能生效

核心 C# 代码如下

_ = Task.Run(async () =>
{
    while (true)
    {
        var display1 = XOpenDisplay(IntPtr.Zero);
        var screen1 = XDefaultScreen(display1);
        try
        {
            await Task.Delay(TimeSpan.FromSeconds(1));
            var result = XIconifyWindow(display1, windowHandle, screen1);
            Console.WriteLine($"XIconifyWindow {result}");
        }
        finally
        {
            XCloseDisplay(display1);
        }
    }
});

以上代码的 windowHandle 的创建代码如下

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

  ... // 忽略其他代码

  var windowHandle = XCreateWindow(display, rootWindow, 0, 0, xDisplayWidth, xDisplayHeight, 5,
      32,
      (int)CreateWindowArgs.InputOutput,
      visual,
      (nuint)valueMask, ref xSetWindowAttributes);

在 Task.Run 里面,不能使用外面 display 对象,否则在 XIconifyWindow 方法将不会返回

如果没有调用 XCloseDisplay 则 XIconifyWindow 的设置是无效的

本文代码放在 githubgitee 上,可以使用如下命令行拉取代码

先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 33dbc36c47d6f1e68265c0f0f389a566823425fd

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码,将 gitee 源换成 github 源进行拉取代码

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 33dbc36c47d6f1e68265c0f0f389a566823425fd

获取代码之后,进入 DikalehebeekaJaqunicobo 文件夹,即可获取到源代码

后续进行更多测试,找到了 XFlush 和 XSync 方法,即不需要创建和关闭 display 对象。但实际测试发现通过如下代码方式,将需要在一定的时机下才能生效,比如鼠标在窗口内晃动,或者重新激活窗口才能生效

_ = Task.Run(async () =>
{
    while (true)
    {
        await Task.Delay(TimeSpan.FromSeconds(1));

        var result = XIconifyWindow(display, handle, screen);

        XFlush(display);
    }
});

完全的代码如下

// See https://aka.ms/new-console-template for more information

using CPF.Linux;
using System;
using System.Diagnostics;
using System.Runtime;
using static CPF.Linux.XLib;

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

var rootWindow = XDefaultRootWindow(display);

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

var valueMask =
        //SetWindowValuemask.BackPixmap
        0
        | SetWindowValuemask.BackPixel
        | SetWindowValuemask.BorderPixel
        | SetWindowValuemask.BitGravity
        | SetWindowValuemask.WinGravity
        | SetWindowValuemask.BackingStore
        | SetWindowValuemask.ColorMap
    //| SetWindowValuemask.OverrideRedirect
    ;
var xSetWindowAttributes = new XSetWindowAttributes
{
    backing_store = 1,
    bit_gravity = Gravity.NorthWestGravity,
    win_gravity = Gravity.NorthWestGravity,
    //override_redirect = true, // 设置窗口的override_redirect属性为True,以避免窗口管理器的干预
    colormap = XCreateColormap(display, rootWindow, visual, 0),
    border_pixel = 0,
    background_pixel = 0,
};

var xDisplayWidth = XDisplayWidth(display, screen) / 2;
var xDisplayHeight = XDisplayHeight(display, screen) / 2;
var handle = XCreateWindow(display, rootWindow, 0, 0, xDisplayWidth, xDisplayHeight, 5,
    32,
    (int)CreateWindowArgs.InputOutput,
    visual,
    (nuint)valueMask, ref xSetWindowAttributes);


XEventMask ignoredMask = XEventMask.SubstructureRedirectMask | XEventMask.ResizeRedirectMask |
                         XEventMask.PointerMotionHintMask;
var mask = new IntPtr(0xffffff ^ (int)ignoredMask);
XSelectInput(display, handle, mask);

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

var white = XWhitePixel(display, screen);
var black = XBlackPixel(display, screen);

var gc = XCreateGC(display, handle, 0, 0);
XSetForeground(display, gc, white);
XSync(display, false);

_ = Task.Run(async () =>
{
    while (true)
    {
        await Task.Delay(TimeSpan.FromSeconds(1));

        var result = XIconifyWindow(display, handle, screen);

        XFlush(display);
    }
});

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

    if (@event.type == XEventName.Expose)
    {
        XDrawLine(display, handle, gc, 0, 0, 100, 100);
    }

    Console.WriteLine(@event.type);
}

Console.WriteLine("Hello, World!");

以上代码放在 githubgitee 上,可以使用如下命令行拉取代码

先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

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

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码,将 gitee 源换成 github 源进行拉取代码

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

获取代码之后,进入 DikalehebeekaJaqunicobo 文件夹,即可获取到源代码

更多 X11 开发请参阅 博客导航


本文会经常更新,请阅读原文: https://blog.lindexi.com/post/dotnet-%E5%90%8E%E5%8F%B0%E7%BA%BF%E7%A8%8B%E8%AE%BE%E7%BD%AE-X11-%E7%AA%97%E5%8F%A3%E6%9C%80%E5%B0%8F%E5%8C%96.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

如果你想持续阅读我的最新博客,请点击 RSS 订阅,推荐使用RSS Stalker订阅博客,或者收藏我的博客导航

知识共享许可协议 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接: https://blog.lindexi.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系

微软最具价值专家


无盈利,不卖课,做纯粹的技术博客

以下是广告时间

推荐关注 Edi.Wang 的公众号

欢迎进入 Eleven 老师组建的 .NET 社区

以上广告全是友情推广,无盈利