using static CPF.Linux.XLib;
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;
//SetWindowValuemask.BackPixmap
| SetWindowValuemask.BackPixel
| SetWindowValuemask.BorderPixel
| SetWindowValuemask.BitGravity
| SetWindowValuemask.WinGravity
| SetWindowValuemask.BackingStore
| SetWindowValuemask.ColorMap
//| SetWindowValuemask.OverrideRedirect
var xSetWindowAttributes = new XSetWindowAttributes
bit_gravity = Gravity.NorthWestGravity,
win_gravity = Gravity.NorthWestGravity,
//override_redirect = true, // 设置窗口的override_redirect属性为True,以避免窗口管理器的干预
colormap = XCreateColormap(display, rootWindow, visual, 0),
var xDisplayWidth = XDisplayWidth(display, screen);
var xDisplayHeight = XDisplayHeight(display, screen);
var width = xDisplayWidth;
var height = xDisplayHeight;
var handle = XCreateWindow(display, rootWindow, 0, 0, width, height, 5,
(int) CreateWindowArgs.InputOutput,
(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);
var gc = XCreateGC(display, handle, 0, 0);
var skBitmap = new SKBitmap(width, height, SKColorType.Bgra8888, SKAlphaType.Premul);
var skCanvas = new SKCanvas(skBitmap);
var xImage = CreateImage(skBitmap);
skCanvas.Clear(SKColors.Blue);
var halfWidth = width / 2;
var halfSkBitmap = new SKBitmap(halfWidth, height, SKColorType.Bgra8888, SKAlphaType.Premul);
var halfSkCanvas = new SKCanvas(halfSkBitmap);
var halfImage = CreateImage(halfSkBitmap);
var newDisplay = XOpenDisplay(IntPtr.Zero);
type = XEventName.Expose,
// [Xlib Programming Manual: Expose Events](https://tronche.com/gui/x/xlib/events/exposure/expose.html )
XLib.XSendEvent(newDisplay, handle, propagate: false,
new IntPtr((int) (EventMask.ExposureMask)),
XCloseDisplay(newDisplay);
var xNextEvent = XNextEvent(display, out var @event);
if (@event.type == XEventName.Expose)
skCanvas.Clear(new SKColor((uint)Random.Shared.Next()).WithAlpha(0xFF));
XPutImage(display, handle, gc, ref xImage, @event.ExposeEvent.x, @event.ExposeEvent.y, @event.ExposeEvent.x, @event.ExposeEvent.y, (uint) @event.ExposeEvent.width,
(uint) @event.ExposeEvent.height);
XPutImage(display, handle, gc, ref halfImage, 0, 0, halfWidth, 0, (uint) halfWidth,
static XImage CreateImage(SKBitmap skBitmap)
const int bytePerPixelCount = 4; // RGBA 一共4个 byte 长度
var bitmapWidth = skBitmap.Width;
var bitmapHeight = skBitmap.Height;
int bitsPerPixel = bytePerPixelCount * bitPerByte;
img.height = bitmapHeight;
img.format = 2; //ZPixmap;
img.data = skBitmap.GetPixels();
img.byte_order = 0; // LSBFirst;
img.bitmap_unit = bitsPerPixel;
img.bitmap_bit_order = 0; // LSBFirst;
img.bitmap_pad = bitsPerPixel;
img.depth = bitsPerPixel;
img.bytes_per_line = bitmapWidth * bytePerPixelCount;
img.bits_per_pixel = bitsPerPixel;