Is a second window possible on Linux with C#?
I've searched the forum and the code samples for a second window/dialog window solution but all i found are tips how to fade-out the current view/render tree and fade-in a new render tree (e. g. the discussion "Simulating modal dialog inside a view"). The fade-out/fade-in approach is good for a full screen presentation. But for a window-based presentation this solution looks strange.
What i'm looking for is a solution with a second window. I have already managed to create, display and close a second GL window, that doesn't disturb or crash the main window. But as soon as i connect the OnPreRender() or OnPostRender() event handler, the application crashes.
What i'm looking for is a solution with a second window. I have already managed to create, display and close a second GL window, that doesn't disturb or crash the main window. But as soon as i connect the OnPreRender() or OnPostRender() event handler, the application crashes.
For me it looks like a renderer confusion. I can not figure out how each renderer determines it's own OpenGL window and connects to it. This is how i create the renderer for the first and second window (every window has it's own class and consequently it's own member attributes _view and _renderer):at <unknown> <0xffffffff>
at (wrapper managed-to-native) Noesis.Renderer.Noesis_Renderer_NeedsOffscreen (System.Runtime.InteropServices.HandleRef) <IL 0x0001a, 0xffffffff>
at Noesis.Renderer.Noesis_Renderer_NeedsOffscreen_ (System.Runtime.InteropServices.HandleRef) <IL 0x00001, 0x00063>
at Noesis.Renderer.NeedsOffscreen () <IL 0x00006, 0x0005b>
at IntegrationSample.DialogWindow.OnPreRender () [0x00013] in /home/rupert/Projects/NoesisGUI/NoesisGUI-IntegrationSample/MainWindow.cs:469
at Noesis.GLUTWrapper.OnPreRender () [0x00010] in /home/rupert/Projects/NoesisGUI/NoesisGUI-IntegrationSample/GLUTWrapper.cs:153
at Noesis.libGLUTWrapper.GLUT_Display () [0x00042] in /home/rupert/Projects/NoesisGUI/NoesisGUI-IntegrationSample/libGLUTWrapper.cs:322
at (wrapper native-to-managed) Noesis.libGLUTWrapper.GLUT_Display () <IL 0x0002f, 0xffffffff>
at <unknown> <0xffffffff>
at (wrapper managed-to-native) Noesis.GLUT.MainLoop () <IL 0x0000e, 0xffffffff>
at Noesis.libGLUTWrapper.GLUT_Run () [0x0009a] in /home/rupert/Projects/NoesisGUI/NoesisGUI-IntegrationSample/libGLUTWrapper.cs:517
at Noesis.GLUTWrapper.Run () [0x00015] in /home/rupert/Projects/NoesisGUI/NoesisGUI-IntegrationSample/GLUTWrapper.cs:291
at IntegrationSample.MainWindow.Run () [0x0018a] in /home/rupert/Projects/NoesisGUI/NoesisGUI-IntegrationSample/MainWindow.cs:269
at IntegrationSample.MainWindow.Main (string[]) [0x001c4] in /home/rupert/Projects/NoesisGUI/NoesisGUI-IntegrationSample/MainWindow.cs:189
at (wrapper runtime-invoke) <Module>.runtime_invoke_void_object (object,intptr,intptr,intptr) <IL 0x00058, 0xffffffff>
private void Run()
{
....
var content = (Noesis.Grid)Noesis.GUI.LoadXaml("TextBox.xaml");
_view = Noesis.GUI.CreateView(content);
_renderer = _view.Renderer;
_renderer.InitGL(new Noesis.VGOptions());
...
}
Any ideas? Thanks in advance!private void Run()
{
...
var content = (Noesis.Grid)Noesis.GUI.LoadXaml("SampleGUI.xaml");
_view = Noesis.GUI.CreateView(content);
_renderer = _view.Renderer;
_renderer.InitGL(new Noesis.VGOptions());
...
}
Re: Is a second window possible on Linux with C#?
The renderer knows nothing about the window. It just uses the current active context. So, you need to make sure that the context that is bound when the renderer is initialized is the same as the one bound when rendering. You probably need two different contexts, one for each window, and you probably want to enable sharing between them, but that's optional.For me it looks like a renderer confusion. I can not figure out how each renderer determines it's own OpenGL window and connects to it. This is how i create the renderer for the first and second window (every window has it's own class and consequently it's own member attributes _view and _renderer):
By they way, I recommend you upgrading to Noesis 2.1, the API is a bit clearer.
Re: Is a second window possible on Linux with C#?
Oh, you are the author of that article. Awesome!
Re: Is a second window possible on Linux with C#?
Hi, you are rigt.
I wanted to get NoisisGUI a little more known to the programmer community. I also introduced NoisisGUI to the German WiKi, because NoisisGUI is not very visible. I plan to add more articles from the perspective of a serious GUI programmer. But I must be sure that NoisisGUI is suitable for the creation of serious GUI.
Back to the question. If it's not bossible to achive this from managed code only, to create a little C or C++ wrapper shared library would not be a show stopper. All that's required for this case is access to the unmanaged pointers, held by the managed code to realize calls into the underlaying native code.
Regards & thanks in advance.
I wanted to get NoisisGUI a little more known to the programmer community. I also introduced NoisisGUI to the German WiKi, because NoisisGUI is not very visible. I plan to add more articles from the perspective of a serious GUI programmer. But I must be sure that NoisisGUI is suitable for the creation of serious GUI.
Back to the question. If it's not bossible to achive this from managed code only, to create a little C or C++ wrapper shared library would not be a show stopper. All that's required for this case is access to the unmanaged pointers, held by the managed code to realize calls into the underlaying native code.
Regards & thanks in advance.
Re: Is a second window possible on Linux with C#?
No, you don't need to create a wrapper at all. Just make sure you are properly creating each GL context and activating them when using the corresponding noesis view. Please, read me previous message again. We have many clients creating several windows with Noesis.Back to the question. If it's not bossible to achive this from managed code only, to create a little C or C++ wrapper shared library would not be a show stopper. All that's required for this case is access to the unmanaged pointers, held by the managed code to realize calls into the underlaying native code.
Re: Is a second window possible on Linux with C#?
Hello jsantos,
thank you for your reply and for your advice regarding der OpenGL context! I've made the necessary changes - but without success. This is the main window initialization:
This is the second window's initialization (no Noisis.GUI calls before GLWindow.InitDialog()):
The methods calls GLWindow.Init() and GLWindow.InitDialog() prepare the OpenGL window and memorize display, drawable, and context:
Both initializations create different values for window, display, drawable, read-drawable and context, e.g.:
Primaty window: 1, 0x16172a0, 0x2c00002, 0x2c00002, 0x162e650
Secondary window: 2, 0x16172a0, 0x2c000f4, 0x2c000f4, 0x241a70e
The GLUT DisplayProcDelegate implementation ensures display, drawable, read-drawable and context are adjusted before any othe call:
But the new code still comes up with the same crash/stack trace. I don't know what to do in addition.
That's why I assume, the adjustment of display, drawable, read-drawable and context works.
But as soon as I enable the '_preRenderCallback' or '_postRenderCallback' the application crashes.
Do I have to ensure by code, that '_view = Noesis.GUI.CreateView(content)' or '_renderer = _view.Renderer' or '_renderer.InitGL(new Noesis.VGOptions())' use the right context?
Is it correct to call '_renderer.InitGL(new Noesis.VGOptions())' for primary and secondary window with Noesis.VGOptions()?
Is the adjustment of display, drawable, read-drawable and context within the GLUT DisplayProcDelegate implementation right or too late?
Is it necessary to adjust display, drawable, read-drawable and context anywhere else in addition?
Thanks in advance.
thank you for your reply and for your advice regarding der OpenGL context! I've made the necessary changes - but without success. This is the main window initialization:
Code: Select all
private void Run()
{
Noesis.GUI.Init();
// Define the resource folder, ALL resources are loaded from. This includes the fonts. The project must provide them.
Noesis.GUI.SetResourceProvider("Data");
// Initialization
_glWindow = GLWindow.Init(800, 600, "NoesisGUI Integration Sample");
// Load the global theme (from resource folder).
var theme = (Noesis.ResourceDictionary)Noesis.GUI.LoadXaml("WindowsStyle.xaml");
Noesis.GUI.SetTheme(theme);
// Data loading (from resource folder)
var content = (Noesis.Grid)Noesis.GUI.LoadXaml("TextBox.xaml");
_view = Noesis.GUI.CreateView(content);
_renderer = _view.Renderer;
_renderer.InitGL(new Noesis.VGOptions());
// Attach to window events
_glWindow.Close += this.OnClose;
_glWindow.Tick += this.OnTick;
_glWindow.PreRender += this.OnPreRender;
_glWindow.PostRender += this.OnPostRender;
_glWindow.Resize += this.OnResize;
_glWindow.MouseMove += this.OnMouseMove;
_glWindow.MouseDown += this.OnMouseDown;
_glWindow.MouseUp += this.OnMouseUp;
_glWindow.KeyDown += this.OnKeyDown;
_glWindow.KeyUp += this.OnKeyUp;
_eventsAttached = true;
// Main Loop
GLUT.SetOption(FreeGLUT.GLUT_ACTION_ON_WINDOW_CLOSE, FreeGLUT.GLUT_ACTION_CONTINUE_EXECUTION);
_glWindow.Run();
// Do cleanup - since FreeGLUT.GLUT_ACTION_ON_WINDOW_CLOSE is set to FreeGLUT.GLUT_ACTION_CONTINUE_EXECUTION,
// GLUT.MainLoop() renturns instead of calling c library exit().
;
}
Code: Select all
public void Run()
{
// Initialization
_glWindow = GLWindow.InitDialog(300, 150, "Dialog");
// Data loading (from resource folder)
var content = (Noesis.Grid)Noesis.GUI.LoadXaml ("SampleGUI.xaml");
_view = Noesis.GUI.CreateView (content);
_renderer = _view.Renderer;
_renderer.InitGL (new Noesis.VGOptions ());
// Attach to window events
_glWindow.Close += this.OnClose;
//_glWindow.PreRender += this.OnPreRender;
//_glWindow.PostRender += this.OnPostRender;
_glWindow.Resize += this.OnResize;
_glWindow.RunInForeignMainLoop();
}
Code: Select all
/// <summary>Init a GL application's first window.</summary>
/// <param name="windowWidth">The GL window client area width.</param>
/// <param name="windowHeight">The GL window client area height.</param>
/// <param name="title">The GL window title.</param>
/// <returns>The <see cref="GLUTWrapper"/> of the window.</returns>
public static GLWindow Init(int windowWidth, int windowHeight, string title)
{
string[] myargv = new string[] { "GLWindow" };
int myargc = 1;
GLUT.Init(myargc, myargv);
GLUT.InitDisplayMode(GLUT.GLUT_RGB | GLUT.GLUT_DOUBLE | GLUT.GLUT_DEPTH | GLUT.GLUT_STENCIL);
// InvokeResize() is automatically called before InvokeRedraw() -> window dimension must not be saved here.
GLUT.InitWindowSize(windowWidth, windowHeight);
GLUT.InitWindowPosition(0, 0);
GLWindow result = new GLWindow(GLUT.CreateWindow(title), GL.XGetCurrentDisplay (),
GL.XGetCurrentDrawable (), GL.XGetCurrentReadDrawable (), GL.XGetCurrentContext ());
return result;
}
/// <summary>Init a GL application's dialog window.</summary>
/// <param name="windowWidth">The GL window client area width.</param>
/// <param name="windowHeight">The GL window client area height.</param>
/// <param name="title">The GL window title.</param>
/// <returns>The <see cref="GLUTWrapper"/> of the dialog.</returns>
public static GLWindow InitDialog(int windowWidth, int windowHeight, string title)
{
// InvokeResize() is automatically called before InvokeRedraw() -> window dimension must not be saved here.
GLUT.InitWindowSize(windowWidth, windowHeight);
GLUT.InitWindowPosition(0, 0);
GLWindow result = new GLWindow(GLUT.CreateWindow(title), GL.XGetCurrentDisplay (),
GL.XGetCurrentDrawable (), GL.XGetCurrentReadDrawable (), GL.XGetCurrentContext ());
return result;
}
Primaty window: 1, 0x16172a0, 0x2c00002, 0x2c00002, 0x162e650
Secondary window: 2, 0x16172a0, 0x2c000f4, 0x2c000f4, 0x241a70e
The GLUT DisplayProcDelegate implementation ensures display, drawable, read-drawable and context are adjusted before any othe call:
Code: Select all
/// <summary>Invoke the registered callbacks for tick, pre-render and post-render.</summary>
/// <remarks>This method is compatible to <see cref="GLUT.DisplayProcDelegate"/>.</remarks>
private void InvokeRedraw()
{
int windowID = GLUT.GetWindow();
if (_windowId != windowID)
{
throw new InvalidOperationException(this.GetType().Name +
$":InvokeRedraw() called for window {windowID} but was designed for window {_windowId}.");
}
// Ensure display, drawable, read-drawable and context are adjusted for the window to redraw.
MakeContext ();
// Frame tick
if (_tickCallback != null)
{
_tickCallback();
}
// PreRender
if (_preRenderCallback != null)
{
_preRenderCallback();
}
// Render Scene (now only a clear)
GL.Enable(GL.GL_DEPTH_TEST);
GL.DepthFunc(GL.GL_LESS);
GL.ClearDepth(1.0f);
GL.DepthMask(GL.GL_TRUE);
GL.Disable(GL.GL_CULL_FACE);
GL.Disable(GL.GL_ALPHA_TEST);
GL.Disable(GL.GL_STENCIL_TEST);
GL.Disable(GL.GL_BLEND);
GL.Disable(GL.GL_SCISSOR_TEST);
GL.UseProgram(0);
GL.BindFramebuffer(GL.GL_FRAMEBUFFER, 0);
GL.Viewport(0, 0, _width, _height);
GL.ColorMask(true, true, true, true);
GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GL.Clear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
GL.LoadIdentity();
// START: Identify window
GLU.Ortho2D(0,400,0,500);
if (windowID == 1)
GL.Color3f(0.5f, 1.0f, 1.0f);
else
GL.Color3f(1.0f, 0.5f, 1.0f);
GL.Begin(GL.GL_POLYGON);
GL.Vertex2i(200,125);
GL.Vertex2i(100,375);
GL.Vertex2i(300,375);
GL.End();
// END: Identify window
GL.Ortho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
// PostRender
if (_postRenderCallback != null)
{
_postRenderCallback();
}
// End
GL.Flush();
GLUT.SwapBuffers();
// Update again and again...
GLUT.PostRedisplay();
}
Since I can't inspect the Noesis code, I don't know which handle Noesis.Renderer.Noesis_Renderer_NeedsOffscreen_ () tries to use - obviously an uninitialized handle (0xffffffff).Stacktrace:
at <unknown> <0xffffffff>
at (wrapper managed-to-native) Noesis.Renderer.Noesis_Renderer_NeedsOffscreen (System.Runtime.InteropServices.HandleRef) <IL 0x0001a, 0xffffffff>
at Noesis.Renderer.Noesis_Renderer_NeedsOffscreen_ (System.Runtime.InteropServices.HandleRef) <IL 0x00001, 0x00063>
at Noesis.Renderer.NeedsOffscreen () <IL 0x00006, 0x0005b>
...
I added code between '// START: Identify window' and '// END: Identify window' to draw differntly colored triangles on primary and secondary window - works fine.Just make sure you are properly creating each GL context and activating them when using the corresponding noesis view.
That's why I assume, the adjustment of display, drawable, read-drawable and context works.
But as soon as I enable the '_preRenderCallback' or '_postRenderCallback' the application crashes.
Do I have to ensure by code, that '_view = Noesis.GUI.CreateView(content)' or '_renderer = _view.Renderer' or '_renderer.InitGL(new Noesis.VGOptions())' use the right context?
Is it correct to call '_renderer.InitGL(new Noesis.VGOptions())' for primary and secondary window with Noesis.VGOptions()?
Is the adjustment of display, drawable, read-drawable and context within the GLUT DisplayProcDelegate implementation right or too late?
Is it necessary to adjust display, drawable, read-drawable and context anywhere else in addition?
Thanks in advance.
Re: Is a second window possible on Linux with C#?
Yes, when calling renderer.InitGL you need to make sure the right context is active because inside that function we create GL resources that are later reused when rendering. But as said before, we changed many things in the API, I recommend updating to the latest version of NoesisGUI before going on.Do I have to ensure by code, that '_view = Noesis.GUI.CreateView(content)' or '_renderer = _view.Renderer' or '_renderer.InitGL(new Noesis.VGOptions())' use the right context?
Is it correct to call '_renderer.InitGL(new Noesis.VGOptions())' for primary and secondary window with Noesis.VGOptions()?
Is the adjustment of display, drawable, read-drawable and context within the GLUT DisplayProcDelegate implementation right or too late?
Is it necessary to adjust display, drawable, read-drawable and context anywhere else in addition?
Re: Is a second window possible on Linux with C#?
Hello jsantos,
thank you for your reply and for your advice regarding new Noesis version. I've changed from version 2.0.2f2 to 2.1.0f1 (libNoesis.so 22.05.2017 ==> 10.03.2018 and NoesisManaged.dll 22.05.2017 ==> 10.03.2018).
There are massive API changes. Now the programmer is forced to create and assign at least an xaml provider (and, where appropriate, a font provider and/or a texture provider) - but all provider implementations are within the NoesisAppManaged.*.dll - which is available only as NoesisAppManaged.Android.dll and NoesisAppManaged.Windows.dll.
I have copied the EmbeddedXamlProvider code into my project (because there is no NoesisAppManaged.Linux.dll) and made all required API changes, but what I get now is:
thank you for your reply and for your advice regarding new Noesis version. I've changed from version 2.0.2f2 to 2.1.0f1 (libNoesis.so 22.05.2017 ==> 10.03.2018 and NoesisManaged.dll 22.05.2017 ==> 10.03.2018).
There are massive API changes. Now the programmer is forced to create and assign at least an xaml provider (and, where appropriate, a font provider and/or a texture provider) - but all provider implementations are within the NoesisAppManaged.*.dll - which is available only as NoesisAppManaged.Android.dll and NoesisAppManaged.Windows.dll.
I have copied the EmbeddedXamlProvider code into my project (because there is no NoesisAppManaged.Linux.dll) and made all required API changes, but what I get now is:
NoesisManaged.dll and libNoesis.so are copied to the compilation output folder. Is there another *.so or *.dll I have to include into the project?SystemDllNotFoundException: Noesis at (wrapper managed-to-native) Noesis.NoesisGUIPINVOKE+SWINGEx)
Re: Is a second window possible on Linux with C#?
EmbeddedXamlProvider is for files embedded inside the executable. You probably don't want that. You can easily implement a Xaml provider that reads files from disk. That way you can have the same behavior you had in previous versions.I have copied the EmbeddedXamlProvider code into my project (because there is no NoesisAppManaged.Linux.dll) and made all required API changes,
You only need libNoesis.so, that error is happening because it cannot be found (Noesis -> libNoesis.so). Are you sure the library is in the same location as the executable?but what I get now is:NoesisManaged.dll and libNoesis.so are copied to the compilation output folder. Is there another *.so or *.dll I have to include into the project?SystemDllNotFoundException: Noesis at (wrapper managed-to-native) Noesis.NoesisGUIPINVOKE+SWINGEx)
PS: forget about NoesisManaged.dll, you don't need it.
Who is online
Users browsing this forum: Ahrefs [Bot] and 1 guest