Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why do you replace void* for Drawable, Pixmap, Window or other? #46

Open
DeafMan1983 opened this issue Dec 10, 2023 · 0 comments
Open
Labels
proposal An issue that represents a proposed feature or change to the repo. untriaged An issue that has not been triaged by the repo maintainers.

Comments

@DeafMan1983
Copy link

DeafMan1983 commented Dec 10, 2023

#Replace void* with nuint

I have resolved with Window.cs from my own.

amespace DeafMan1983.Interop.X11;

[NativeTypeName("typedef unsigned long XID")]
public readonly struct XID
{
    public readonly nuint Handle;

    public XID(nuint value)
    {
        Handle = value;
    }

    public static explicit operator XID(nuint value) => new XID(value);
    public static implicit operator nuint(XID xid) => xid.Handle;
}

And example with Drawable

amespace DeafMan1983.Interop.X11;

[NativeTypeName("typedef XID Drawable")]
public struct Drawable
{
    public XID Handle;

    public Drawable(XID id)
    {
        Handle = id;
    }

    public static bool operator ==(Drawable left, Drawable right)
    {
        return left.Handle == right.Handle;
    }

    public static bool operator !=(Drawable left, Drawable right)
    {
        return left.Handle != right.Handle;
    }

    public static bool operator <(Drawable left, Drawable right)
    {
        return left.Handle < right.Handle;
    }

    public static bool operator <=(Drawable left, Drawable right)
    {
        return left.Handle <= right.Handle;
    }

    public static bool operator >(Drawable left, Drawable right)
    {
        return left.Handle > right.Handle;
    }

    public static bool operator >=(Drawable left, Drawable right)
    {
        return left.Handle >= right.Handle;
    }

    public static bool operator ==(Drawable left, XID right) => left.Handle == right;
    public static bool operator !=(Drawable left, XID right) => left.Handle == right;

    public static implicit operator Drawable(XID id) => new Drawable(id);
    public static implicit operator XID(Drawable drawable) => drawable.Handle;

    public static explicit operator Drawable(Window window) => new Drawable(window);
    public static implicit operator Window(Drawable drawable) => new Drawable(drawable);

    public override bool Equals(object? obj) => (obj is Drawable other) && Equals(other);

    public bool Equals(Drawable other) => ((nuint)Handle).Equals((nuint)other.Handle);

    public override int GetHashCode() => ((nuint)Handle).GetHashCode();
}

And Window.

namespace DeafMan1983.Interop.X11;

[NativeTypeName("typedef XID Window")]
public unsafe readonly struct Window
{
    public readonly XID Handle;

    public Window(XID id)
    {
        Handle = id;
    }

    public static bool operator ==(Window left, Window right)
    {
        return left.Handle == right.Handle;
    }

    public static bool operator !=(Window left, Window right)
    {
        return left.Handle != right.Handle;
    }

    public static bool operator <(Window left, Window right)
    {
        return left.Handle < right.Handle;
    }

    public static bool operator <=(Window left, Window right)
    {
        return left.Handle <= right.Handle;
    }

    public static bool operator >(Window left, Window right)
    {
        return left.Handle > right.Handle;
    }

    public static bool operator >=(Window left, Window right)
    {
        return left.Handle >= right.Handle;
    }

    public static bool operator ==(Window left, XID right) => left.Handle == right;
    public static bool operator !=(Window left, XID right) => left.Handle == right;

    public static explicit operator Window(XID id) => new Window(id);
    public static implicit operator XID(Window window) => window.Handle;

    public static explicit operator Window(Drawable drawable) => new Window(drawable);
    public static implicit operator Drawable(Window window) => new Drawable(window);

    public override bool Equals(object? obj) => (obj is Window other) && Equals(other);

    public bool Equals(Window other) => ((nuint)Handle).Equals((nuint)other.Handle);

    public override int GetHashCode() => ((nuint)Handle).GetHashCode();
}

Result:
It works fine like original X11 C <-> C#

namespace DeafMan1983.X11Test;

using DeafMan1983.Interop.X11;
using static DeafMan1983.Interop.X11.X11;

using static DeafMan1983.ConvFunctions;

unsafe class Program
{
    static int Main(string[] args)
    {
        try
        {
            if (args.Length == 1 && args[0] == "--version")
            {
                Console.WriteLine(@"
                    CopyRight 2023, Jens-Peter Eckervogt, aka DeafMan1983, Germany
                    Author: Jens-Peter Eckervogt
                    Description: This app was written in C#.
                ");
            }
            else
            {
                Display* display = XOpenDisplay(null);
                if (display == null)
                {
                    Console.WriteLine("Error: Initializing X11!");
                    return -1;
                }

                int scr_nbr = XDefaultScreen(display);
                int screen_width = XDisplayWidth(display, scr_nbr);
                int screen_height = XDisplayHeight(display, scr_nbr);

                int win_w = 400;
                int win_h = 400;

                Window win = XCreateSimpleWindow(display, XRootWindow(display, scr_nbr), 0, 0, (uint)win_w, (uint)win_h, 0, XBlackPixel(display, scr_nbr), XWhitePixel(display, scr_nbr));
                if (win == NULL)
                {
                    Console.WriteLine("Error: Creating X11's Window");
                    return -1;
                }

                XSelectInput(display, win, KeyPressMask | ExposureMask | SubstructureRedirectMask);

                Atom wm_protocol = XInternAtom(display, SBytePointerFromString("WM_PROTOCOLS"), False);
                Atom wm_delete_window = XInternAtom(display, SBytePointerFromString("WM_DELETE_WINDOW"), False);
                XSetWMProtocols(display, win, &wm_delete_window, 1);
                XStoreName(display, win, SBytePointerFromString("Hello X11 Window"));

                XMapWindow(display, win);

                int center_w = (screen_width - win_w) / 2;
                int center_h = (screen_height - win_h) / 2;
                XMoveWindow(display, win, center_w, center_h);

                XFlush(display);

                GC* gc = XDefaultGC(display, scr_nbr);
                const int step = 15;
                const int rects_number = 40;
                XRectangle[] rectangles = new XRectangle[rects_number];
                XEvent evt;
                while (true)
                {
                    XNextEvent(display, &evt);
                    if (evt.type == KeyPress)
                    {
                        if (evt.xkey.keycode == 0x09)
                        {
                            break;
                        }
                    }

                    if (evt.type == ClientMessage)
                    {
                        if (evt.xclient.message_type == wm_protocol &&
                            evt.xclient.data.l[0] == wm_delete_window)
                        {
                            break;
                        }
                    }

                    if (evt.type == Expose && evt.xexpose.count == 0)
                    {
                        for (int i = 0; i < rects_number; i++)
                        {
                            rectangles[i].x = (short)(i * step);
                            rectangles[i].y = (short)(i * step);
                            rectangles[i].width = step * 2;
                            rectangles[i].height = step * 2;
                        }

                        fixed (XRectangle* rectPtr = rectangles)
                        {
                            XDrawRectangles(display, win, gc, rectPtr, rects_number);
                        }
                    }
                }

                XDestroyWindow(display, win);
                XCloseDisplay(display);
            }
        }
        catch (Exception exc) 
        {
            Console.WriteLine("Error: {0}", exc.Message);
        }
        
        return 0;
    }
}

I would like to show you.
image

No problem for me! I saw in repository and your structures's implicit and explicit are wrong because you won't to write Handle indeed of Window or Drawable or you check if (window = NULL) { ... }

NULL is XID for XID-used structures and if you ATOM, Font or GContext cast with (long) or (nuint) with XID's NULL.

I write simple XID's NULL:

    // Hack trick: It just is a NULL == null.
    public readonly static XID NULL = new XID(0);

Have nice weekend and merry Christmas!

@DeafMan1983 DeafMan1983 added proposal An issue that represents a proposed feature or change to the repo. untriaged An issue that has not been triaged by the repo maintainers. labels Dec 10, 2023
@DeafMan1983 DeafMan1983 changed the title Why do you replace void* for Drawable, Why do you replace void* for Drawable, Pixmap, Window or other? Dec 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal An issue that represents a proposed feature or change to the repo. untriaged An issue that has not been triaged by the repo maintainers.
Projects
None yet
Development

No branches or pull requests

1 participant