Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Porting from SFML example with X11 - Nice one!  (Read 9143 times)

0 Members and 1 Guest are viewing this topic.

DeafMan1983

  • Newbie
  • *
  • Posts: 3
    • View Profile
Porting from SFML example with X11 - Nice one!
« on: February 28, 2021, 04:46:44 pm »
Hello everyone,

Thanks for welcome saying for me! I am new for here.

I thought SFML is better than SDL2 or Allegro5.

I have made one X11 with SFML with Mono 6.12.x = It works fine like chain. But I can't understand why does it throw BadDrawable in X11

I think VisualInfo  is not XDefaultVisual() - It looks like advanced mode with Visual like GLX on X11.

I have made one nice example:
using System;
using System.Runtime.InteropServices;
using SFML.Graphics;

using static X11SFML.X11;

namespace X11SFML
{
    static class X11
    {
        public enum XEventType
        {
            KeyPress = 2
        }

        [StructLayout(LayoutKind.Explicit)]
        public struct XEvent
        {
            [FieldOffset(0)]
            public XEventType type;
        }

        public enum XEventMask : long
        {
            KeyPressMask = 1L << 0
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct XSetWindowAttributes
        {
            public uint background_pixel;
            public XEventMask event_mask;
        }

        [Flags]
        public enum CWAttributes : long
        {
            CWBackPixel = 1L << 1,
            CWEventMask = 1L << 11
        }

        private const string libX11 = "libX11.so.6";

        [DllImport(libX11)]
        public extern static IntPtr XOpenDisplay(string display_name);

        [DllImport(libX11)]
        public extern static void XCloseDisplay(IntPtr x_display);

        [DllImport(libX11)]
        public extern static int XDefaultScreen(IntPtr x_display);

        [DllImport(libX11)]
        public extern static int XDefaultDepth(IntPtr x_display, int screen_number);

        [DllImport(libX11)]
        public extern static IntPtr XDefaultVisual(IntPtr x_display, int screen_number);

        [DllImport(libX11)]
        public extern static IntPtr XRootWindow(IntPtr x_display, int screen_number);

        [DllImport(libX11)]
        public extern static uint XBlackPixel(IntPtr x_display, int screen_number);

        [DllImport(libX11)]
        public extern static IntPtr XCreateWindow(IntPtr x_display, IntPtr x_window_parent, int x, int y, uint width, uint height, uint border_width, int depth, uint window_class, IntPtr visual, CWAttributes cws, ref XSetWindowAttributes attributes);

        [DllImport(libX11)]
        public extern static IntPtr XCreateWindow(IntPtr x_display, IntPtr x_window_parent, int x, int y, uint width, uint height, uint border_width, int depth, uint window_class, IntPtr visual, CWAttributes cws, IntPtr attributes);

        [DllImport(libX11)]
        public extern static void XStoreName(IntPtr x_display, IntPtr x_window, string title);

        [DllImport(libX11)]
        public extern static void XSync(IntPtr x_display, bool discard);

        [DllImport(libX11)]
        public extern static void XMapWindow(IntPtr x_display, IntPtr x_window);

        [DllImport(libX11)]
        public extern static void XFlush(IntPtr x_display);

        [DllImport(libX11)]
        public extern static bool XPending(IntPtr x_display);

        [DllImport(libX11)]
        public extern static void XNextEvent(IntPtr x_display, out XEvent x_event);
    }

    class MainClass
    {
        private const int EXIT_SUCCESS = 0;
        private const int EXIT_FAILURE = 1;

        static int Main(string[] args)
        {
            Console.WriteLine("Hello X11 with SFML!");
            IntPtr display = XOpenDisplay(null);
            if (display == IntPtr.Zero)
            {
                return EXIT_FAILURE;
            }
            else
            {
                Console.WriteLine("Display opened - SUCCESS");
            }

            int screen_number = XDefaultScreen(display);

            int depths = XDefaultDepth(display, screen_number);
            IntPtr root_window = XRootWindow(display, screen_number);
            IntPtr visual = XDefaultVisual(display, screen_number);

            XSetWindowAttributes attributes = new XSetWindowAttributes
            {
                background_pixel = XBlackPixel(display, screen_number),
                event_mask = XEventMask.KeyPressMask
            };

            IntPtr main_window = XCreateWindow(display, root_window, 0, 0, 650, 330, 0, depths, 1, visual, CWAttributes.CWBackPixel | CWAttributes.CWEventMask, ref attributes);
            if (main_window == IntPtr.Zero)
            {
                return EXIT_FAILURE;
            }
            else
            {
                Console.WriteLine("Window created - SUCCESS");
            }

            XStoreName(display, main_window, "SFML in X11 - Mono 6.12.x");

            IntPtr view1 = XCreateWindow(display, main_window, 10, 10, 310, 310, 0, depths, 1, visual, 0, IntPtr.Zero);
            IntPtr view2 = XCreateWindow(display, main_window, 330, 10, 310, 310, 0, depths, 1, visual, 0, IntPtr.Zero);

            XMapWindow(display, main_window);
            XFlush(display);

            RenderWindow forView1 = new RenderWindow(view1);
            RenderWindow forView2 = new RenderWindow(view2);

            forView1.SetActive();
            forView1.Clear(Color.Red);

            forView2.SetActive();
            forView2.Clear(new Color(255, 102, 0, 255));

            bool running = true;
            while (running)
            {
                while (XPending(display))
                {
                    XNextEvent(display, out XEvent evt);
                    switch (evt.type)
                    {
                        case XEventType.KeyPress:
                            running = false;
                            break;
                    }
                }

                CircleShape circle = new CircleShape
                {
                    FillColor = Color.Yellow,
                    Radius = 50f,
                    Position = new SFML.System.Vector2f(105, 105)
                };

                forView1.Draw(circle);

                RectangleShape rectangle = new RectangleShape
                {
                    FillColor = new Color(33, 33, 33),
                    Size = new SFML.System.Vector2f(100, 100),
                    Position = new SFML.System.Vector2f(105, 105)
                };

                forView2.Draw(rectangle);

                forView1.Display();
                forView2.Display();
            }

            XCloseDisplay(display);

            return EXIT_SUCCESS;
        }
    }
}

Screenshot:


Enjoy your coding with Mono/Dotnet

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: Porting from SFML example with X11 - Nice one!
« Reply #1 on: March 01, 2021, 09:24:33 am »
Why are you using X11 directly?
You can just use SFML's window, which will use X11 underneath for you.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

DeafMan1983

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: Porting from SFML example with X11 - Nice one!
« Reply #2 on: March 01, 2021, 08:21:23 pm »
Because I try for porting from C++ to C# -

It works fine under GtkSharp 2 / 3 too yay. If I use Events = Gdk.EventMask.AllEventMasks than it will crash. So sad with Gdk.Event :(

using System;
using System.Runtime.InteropServices;

using SFML.Graphics;
using SFML.Window;

namespace GtkSharp2SFML
{
    public class RenderWidget : Gtk.DrawingArea
    {
        private const string libgdk_x11 = "libgdk-x11-2.0.so.0";

        [DllImport(libgdk_x11)]
        private extern static IntPtr gdk_x11_drawable_get_xid(IntPtr gdk_window);

        private IntPtr GraphicsHandle
        {
            get
            {
                return gdk_x11_drawable_get_xid(GdkWindow.Handle);
            }
        }

        public RenderWindow RenderWindow { get; private set; }

        public RenderWidget()
        {
            AppPaintable = true;
            DoubleBuffered = false;
            CanFocus = true;
        //    Events = Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.KeyPressMask | Gdk.EventMask.KeyReleaseMask;
        }

        protected override bool OnExposeEvent(Gdk.EventExpose evnt)
        {
            bool ok = base.OnExposeEvent(evnt);
            ContextSettings settings = new ContextSettings
            {
                DepthBits = 24
            };
            RenderWindow = new RenderWindow(GraphicsHandle, settings);
            RenderWindow.DispatchEvents();
            RenderWindow.SetFramerateLimit(60);
            RenderWindow.DefaultView.Viewport = new FloatRect(evnt.Area.X, evnt.Area.Y, evnt.Area.Width, evnt.Area.Height);
            Realize();
            OnRender();
            evnt.Window.Display.Sync();
            RenderWindow.Display();
            QueueDraw();
            return ok;
        }

        public event EventHandler Rendered;

        protected virtual void OnRender()
        {
            if (Rendered != null)
                Rendered(this, EventArgs.Empty);
        }

        protected override void OnDestroyed()
        {
            RenderWindow.Close();
            base.OnDestroyed();
        }
    }
}

And I try to communicate with Gtk.Button - It works fine!!! Without SFML-Events. I can't expect that SDL2 is really loser and SFML is winner. Congratulations!! I am happy because I have tried since GtkSharp 2 / 3 with SDL2 = Crashed if you add Button. It stopped to run :( So sad. I try to communicate with any controls like you use C# example Windows.Forms, MonoMac or XlibSharp
using System;
using System.Runtime.InteropServices;

using SFML.Graphics;
using SFML.System;
using SFML.Window;

namespace GtkSharp2SFML
{
    class MainClass
    {
        static RenderWidget render_widget;
        //   static byte bvalue = 0x00;
        private static bool color_changed = true;

        [STAThread]
        static void Main(string[] args)
        {
            Gtk.Application.Init();
            Gtk.Window main_window = new Gtk.Window(Gtk.WindowType.Toplevel)
            {
                Title = "SFML in GtkSharp 2",
                WindowPosition = Gtk.WindowPosition.Center
            };
            main_window.SetSizeRequest(400, 300);

            Gtk.VBox main_area = new Gtk.VBox(false, 0);
            main_window.Add(main_area);
            render_widget = new RenderWidget();
            main_area.PackStart(render_widget, true, true, 0);
            color_changed = false;
            render_widget.Rendered += OnRender;

            Gtk.Button changecolor = new Gtk.Button
            {
                Label = "Change Color",
            };
            main_area.PackStart(changecolor, false, false, 0);
            changecolor.Clicked += OnChangeColor;

            main_window.Destroyed += delegate {
                Gtk.Application.Quit();
            };

            main_window.ShowAll();
            Gtk.Application.Run();
        }

        private static void OnChangeColor(object sender, EventArgs e)
        {
            color_changed = true;
            if (color_changed)
            {
                render_widget.RenderWindow.DispatchEvents();
                render_widget.RenderWindow.Clear(Color.Blue);
                render_widget.RenderWindow.Display();
            }
        }

        private static void OnRender(object sender, EventArgs e)
        {
            if (!color_changed)
            {
                render_widget.RenderWindow.Clear(Color.Red);
                color_changed = false;
            }
        }
    }
}
Result:
It runs app

And I clicked button to blue color.


Enjoy and happy coding with GtkSharp 2 and 3 = OK. Please remember and do not use EventMask in code.because EventMask can stop to run Gtk applications.

PS: You know I have found old thread of GraphicsWidget - But it seems like it doesn't work because it has forgotten:
AppPaintable and CanFocus and resizing viewport of SFML.

My own RenderWidget is better than GraphicsWidget.
Resizing = YES
Communicating = for Buttons/Menus = YES, for Text = NOT TESTED, Image into SFML Teexture, NOT TESTED and any...
Closing = YES , It works fine

GraphicsWidget from old thread since I found here.:
Resizing = FAILED NO - HAHAHA
Communicating = DON'T KNOW ???
Closing = FAILED NO - HAHAHA

// EDIT
Great news with Events = Gdk.EventMask.AllEventMasks - no crash because EventMask works fine under ExposeEvent.

It looks like my code and it fixes and it doesn't crash. But I am not sure if it works.
        protected override bool OnExposeEvent(Gdk.EventExpose evnt)
        {
            bool ok = base.OnExposeEvent(evnt);
            ContextSettings settings = new ContextSettings
            {
                DepthBits = 24,
                StencilBits = 8
            };
            RenderWindow = new RenderWindow(GraphicsHandle, settings);
            RenderWindow.SetVerticalSyncEnabled(true);
            RenderWindow.SetFramerateLimit(60);
            RenderWindow.DefaultView.Viewport = new FloatRect(evnt.Area.X, evnt.Area.Y, evnt.Area.Width, evnt.Area.Height);
            OnRender();
            evnt.Window.Display.Sync();
            while (ok && RenderWindow.IsOpen)
            {
                RenderWindow.DispatchEvents();
                Events = Gdk.EventMask.AllEventsMask;
            }
            RenderWindow.Display();
            QueueDraw();
            return ok;
        }

But it shows like common failure lines under library - I think SFML libraries have thrown failures.
Failed to create input context for window -- TextEntered event won't be able to return unicode

It looks like for my Gtk Application runs fine and doesn't crash. Yay! It works fine. - I know I have found old threads I have readden about "Failure to create input..." That is reason because it calls "code-failure", right or I understand wrongly? Sorry my bad English.

// Update
ColorButton can communicate to SFML's Clear(color) Woohoooo! ColorButton changes color of SFML's Clear() = OK 100 %

It is easy simple trick

Remember that Gdk.Color's bit is ushort and I calculate to byte
65535 / 257 = 255 -> byte maxvalue in SFML.Color's bit.

// EDIT 2:
Found bug GtkSharp 2 can't show when you maximize Gtk Window and RenderWindow can't change color. That is why I need move to GtkSharp 3.x = OK - Since I tested with Gtk.GLArea()

Sorry for disturbances of edits....
« Last Edit: March 02, 2021, 01:13:47 pm by DeafMan1983 »