OpenTK 4.0 + Gtk# bindings initialization - c#

I am currently trying to draw into a GLArea of Gtk#. Gtk# sadly doesn't come with the GL functions and only provides context creation.
I am now trying for days to get the latest prerelease of OpenTK (4.0.0-pre.10) work with Gtk#'s GLArea.
using Gtk;
using OpenToolkit.Graphics.OpenGL4;
using OpenToolkit.Windowing.GraphicsLibraryFramework;
namespace Test
{
class Viewport : GLArea
{
protected override bool OnRender(Gdk.GLContext context)
{
GL.ClearColor(0.3f, 0.3f, 0.3f, 1.0f);
GL.Clear(ClearBufferMask.ColorBufferBit);
return true;
}
}
class MainWindow : Gtk.Window
{
public MainWindow() : base(WindowType.Toplevel)
{
this.Add(new Viewport());
}
}
class Program
{
static void Main(string[] args)
{
GLFW.Init();
GL.LoadBindings(new GLFWBindingsContext());
Application.Init();
var window = new MainWindow();
window.ShowAll();
Application.Run();
}
}
}
The problem is that the GL functions seem to not get loaded, the first attempt to call one of them gives a System.AccessViolationException.
I couldn't really find any information on how to initialize the OpenTK 4.0 bindings. OpenTK 3 had OpenTK.Toolkit.Init() which seems to be exactly what i need.
Documentation for OpenTK.Toolkit.Init:
"You must call this method if you are combining OpenTK with a third-party windowing toolkit (e.g. GTK#). In this case, this should be the first method called by your application"
I can't find this function or something similar in version 4. It seems like it just got removed.
I can't use OpenTK 3 either because it lacks support for .Net Core. I get everything to work by creating a OpenTK dummy window and instantly throw it away. That initializes the GL.* functions but you see the second window opening and closing for a second. I really don't want to use workarounds like that.
Does anyone have any insight on how to properly initialize the OpenTK 4.0 bindings? I mean, there has to be a way, the bindings would essentially be useless for a lot of use cases otherwise.

First of all using the GLFW bindings requires an active Opengl Context created by it and seconds of all you might want to use some other bindings context, sadly they provide only the one for GLFW because that's what they chose to use for windowing.
I have made a bindings context that works for Linux and with the help of someone I made something that will work on both windows too. You can grab it from here https://gist.github.com/NepNet/e4e75defb3748f76f10302b585b9839b. I suggest loading the bindings in the OnRealized event of the GLArea and make it's context current if you use the NativeBindingsContext because OpenGL on windows requires an active context for it to return valid pointers the other 2 files are required by it but if you want to target only one platform you can use only the glx context for linux and wgl for windows
edited:
You can load the bindings before starting the gtk app because glx doesn't require an active context to return the function pointers but I sugest loading them in the OnRealized event of the GLArea with an optional static boolean to not load them more than once and If you want to do GL calls in the onrealized I suggest to make the context of the area curent and as for windows I don't have a solution yet, tried with 'opengl32.dll' and wglGetProcAddress and seems to return 0 most of the time even with an active context

Related

How to make a listener of a service on android

I have this code to check if a service is active, but I would like to know if there is any way for an EditText to show the status of the service, without making this query per second, or in a separate thread, or linking it in some way? that it is possible to detect if the service stopped
private bool MiServicioEstaCorriendo(Class #class, Context contexto)
{
ActivityManager manager = (ActivityManager)contexto.GetSystemService(Context.ActivityService);
foreach (ActivityManager.RunningServiceInfo service in manager.GetRunningServices(Integer.MaxValue))
{
if (#class.Name.Equals(service.Service.ClassName))
{
Log.Info(typeof(BroadcastGps).Name, "MiServcicioEstaCorriendo: true");
return true;
}
}
Log.Info(typeof(BroadcastGps).Name, "MiServcicioEstaCorriendo: false");
return false;
}
You are basically in need of a way to pass events/messages among classes within your application. So this question probably goes down to Android & C# implementation of such a pattern. Xamarin.Forms has a MessagingCenter class, but since you are using Xamarin.Native, you would have to create something yourself
There's nothing actually already baked in to Android or C#, but so you can implement one of the most common ways to let a class spread an event/message using the "Listener" (term used in Android) or "Delegate" (term used in C#) technique.
There are frameworks too like PubNub that you can use as Nuget packages that simplify everything for you.
Some more resources to understand the concept: Wikipedia, IBM.
And Some Android resources: Handlers, AsyncTasks, Parcelables.
Don't forget that your event to update your EditText may not be fired on the Main UIThread so you won't be able to see the changes unless you force that update line to be Run on UI Thread.

C# Add custom Windows context menu for just this program

My question is: How do I add a windows context menu item for a specific application, not globally?
Quick Brief:
We use Access (groan) for our CRM system. We use a basic 'copy to local' process for multi-access. I have written a C# 'launcher' of which handles this much better than a .bat file (they click the launcher, the launcher downloads the db, launches the db and quits). I also currently use a C# console application to handle development, automating stuff like incrementing version number, moving files around etc.
My Question/Goal:
I want to combine the two programs into one but I don't want to hinder the launcher from it's main purpose by jarring the user asking if they want to develop or not. I use this launcher too as I am primarily an estimator, hence wanting to combine the two. I have read that you can add context menu items to Windows as a whole, but I want to be able to add a launch option into the context menu just for this application. i.e. right click on program, normal menu options but with the addition of "Development Mode", this opens the program with arguments that I can use to open the development window/console instead.
Things to note:
I have played around with holding a key on start but it can be vague when to press the key. Too early - you will end up typing "r" several times into the active window, too late - and it will miss the capture point.
I have also looked at having a button on the launcher that gives you the option to go into dev mode, but the launcher is only open for around a second so its really easy to miss.
Thanks in advance
EDIT: The launcher is made and run as a click-once app.
I dont really know about whether its possible to have a custom context for a specific program, as far as i know the context works with the extension. That being said, i think there are better ways to handle your problem. Have a look at this
static void Main(string[] args)
{
/* here normal flow of the launcher*/
if (args[0] == "-dev")
{
/*here de developer mode*/
Console.WriteLine("Developer mode activated");
}
}
The way to use it is simple, you make a shorcut, and where it says the shorcut target you will have something like this "C:\Users****\Documents\visual studio 2017\Projects\Test\Test\bin\Debug\Test.exe" and you should change it to something like this "C:\Users****\Documents\visual studio 2017\Projects\Test\Test\bin\Debug\Test.exe" -dev
Further to this I stumbled upon some code to make this work. Hopefully this will help someone in the future. I am doing this in WPF, but I am sure you could probably adapt this code to work elsewhere.
1) App.xaml - Adding the JumpList action
After (not inside) the Application.Resources property add the following and change to your liking (There are a lot of properties I haven't used for development sake, check out the link to learn more):
<Application.Resources>
...
</Application.Resources>
<JumpList.JumpList>
<JumpList ShowRecentCategory="False"
ShowFrequentCategory="False">
<JumpTask Title="Open Dev Mode"
Description="Use this to enter dev mode (admins only)"
Arguments="DevMode:true"/>
</JumpList>
</JumpList.JumpList>
This will create a "Task" in the jump list:
2) Create Global static class - this will allow you to store the variable for later use in other forms.
public static class Global
{
public static Boolean DevMode = false;
}
3) App.xaml.cs - Adding OnStartup handler
Inside the App class create an override method for OnStartup
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
Global.DevMode = Boolean.Parse(e.Args.FirstOrDefault().ToString().Split(':')[1]);
}
}
4) Read the variable in your form using Global.DevMode
private void Window_ContentRendered(object sender, EventArgs e)
{
if (Global.DevMode) RunYourDevScript();
}
As per a suggestion in a comment, that has gone for some reason. I am going to revert to keypress but use shift instead or "R".
Failing this, or if it causes problems it will look at creating a global context menu item for all programs, and just won't click it when I don't need to

How to fake background activity while using Xamarin.UITest

I'm creating a Xamarin.Forms App and want to use UITest to test the correct behavior of my View. The View does not only react on user input like button click or the like. Instead there are background operations which should lead to changes in the View like hiding one element and showing another element at this point. Another example is filling a ListView with elements which would be produced by a background operation. These changes would be made on the ViewModel whose properties are bound to the View.
Now I want to simulate the background operation and test that my View behaves correctly. But I can not manipulate my ViewModel while in the UITest project because I cannot reference Xamarin.Forms in the Test class.
It seems like it isn't intended to test the application this way. The whole app is a black box for the UITest and you can only interact through mouse and keyboard input with it.
How can I access internals of my app, the corresponding ViewModel for example.
I already searched for this problem but found nothing. Maybe I'm searching in the wrong direction.
Any help would be highly appreciated.
You can use a back door to access a method in a platform project, and from there you should be able to access Forms code since your app project references the Forms core project. See: https://developer.xamarin.com/guides/testcloud/uitest/working-with/backdoors/
Create backdoor method in Android project:
In MainActivity:
[Export("MyBackdoorMethod")]
// Can optionally take a parameter of string, int, or bool.
// Can optionally return string or Java.Lang.String.
public void MyBackdoorMethod()
{
// In through the backdoor - do some work.
}
To call the Android backdoor method from a test:
app.Invoke("MyBackdoorMethod");
Create backdoor method in iOS project:
In AppDelegate:
[Export("myBackdoorMethod:")] // notice the colon at the end of the method name
// Must take an NSString and return an NSString.
public NSString MyBackdoorMethod(NSString value)
{
// In through the backdoor - do some work.
}
To call the iOS backdoor method from a test:
app.Invoke("myBackdoorMethod:", "the value");
More details at the link, but this should suffice to get one going.
On iOS, you already have a method to achieve it called SendAppToBackground. You can also pass the time to be in the background with a TimeSpan object (wiki info). However, you cannot achieve this on Android.
Here is a sample to use it on your UITest project:
public void SendAppToBackground(IApp app, TimeSpan timeSpan)
{
if (OnAndroid)
{
return;
}
((iOSApp)app).SendAppToBackground(timeSpan);
app.Screenshot("Return from background state.");
return this;
}

Where to initialize PCL instanced in a Xamarin.iOS app?

I'm working on a Xamarin application, which I will at first have working on iOS, but plan to later expand to Android and other mobile platforms.
As such, I'm trying to keep as much common code in PCLs as possible.
My question: what is the best practise - in Xamarin.iOS for now - to initialize any dependent PCL code?
For now I have it in the RootViewController inside ViewDidLoad()
public override void ViewDidLoad()
{
base.ViewDidLoad();
_engine = new MyEngine();
View = new MainView(_engine);
}
Is this the right spot? I'd considered putting it in the ctor for the RootViewController, but there's a fair bit going on in the initialization code, which thus ran against "don't put heavy duty init code into a constructor".
Things that happen are:
Load app settings
If app is run for first time ever, load basic defaults
Initialise other PCL libraries, such as a TextToSpeech module, a state engine (hence the name of the class above), etc
Prepare a data grid based on XML or JSON input
Alternately, I though it should possibly go into the AppDelegate section, but that didn't sound right.
I'm still fairly new to mobile app dev in general and Xamarin in specific, though I've done C# native code for Windows for years. I just want to make sure I follow best practises, but there doesn't seem to be a "thou shalt" in this case.
Edit: I've extracted the solution based on #wishmaster's suggestions.
For iOS the Appdelegate method is the best place for initialization code. The appdelegate also provides multiple delegate methods to give you feedback on application lifecyle events such as the method "DidFinishLauchingWithOptions"
. if you have a lot of data to download or long running tasks that your app depends on I would suggest you take a look backgrounding for iOS.
A technique I have also used is for my first viewcontroller on IOS (or activity on Android) to display a splash screen and a loading indicator while i run some code to refresh the cache.
Using #wishmaster's pointers, this solution works like a charm:
In AppDelegate.cs
// in the global section put any data you may make available elsewhere
private var _engine;
public Engine => _engine;
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
/*
* Do whatever init needs to happen here, if you need to make this
* available elsewhere, ensure you have properties or accessors,
* as above.
*/
_engine = new MyEngine();
return true;
}
Then in RootViewController.cs using a similar approach to these examples in Obc-C or Swift you can access the information through a property pointing at the AppDelegate.
var myappdelegate = UIApplication.SharedApplication.Delegate as AppDelegate;
var engine = myappdelegate.Engine;
View = new MainView(engine);
The result resulted in a snappier start up of the application, because the initialisation now happens during the splash screen and no longer between splash screen and appearance of the UI.

Executing UI Code from ViewModel on MVVMCross

I have just started using MvvmCross, but i didn't find any info about to how i can execute UI code from a ViewModel.
On Caliburn there are coroutine so i can access the view and keep the ui code separated from the viewmodel code.
on my first case i need to open a dialow from a command inside a ViewModel, what is the correct way?
Right now i'm developing a WinRT app.
Thanks
There isn't any hard/fast rule on this within MvvmCross.
Generally, when I need to do this I use the Messenger plugin.
This answer assumes you are using the latest Alpha v3 code. For older vNext code you'll have to do some translation - see notes below.
To use this approach:
I reference Cirrious.MvvmCross.Plugins.Messenger.dll from both Core and UI projects.
Then I add a line somewhere in Setup.cs (e.g. in InitializeLastChance) to:
Cirrious.MvvmCross.Plugins.Messenger.PluginLoader.Instance.EnsureLoaded();
Then in the Core project I add a message:
public class InputIsNeededMessage : MvxMessage
{
public InputIsNeededMessage(object sender) : base(sender) {}
}
In the ViewModel I can get the Messenger by constructor injection or by:
var messenger = Mvx.Resolve<IMvxMessenger>();
and I can send messages by calling:
messenger.Publish(new InputIsNeededMessage(this));
In the View I can again get to the messenger and subscribe to messages using:
var messenger = Mvx.Resolve<IMvxMessenger>();
_token = messenger.SubscribeOnMainThread<InputIsNeededMessage>(OnInputIsNeeded);
where _token must be a member variable - if it isn't then the subscription won't persist - the subscription itself is weak by default (so you never have to unsubscribe)
and where OnInputIsNeeded is something like:
private void OnInputIsNeeded(InputIsNeededMessage message)
{
if (message.Sender != ViewModel)
return;
// do stuff here - you are already on the UI thread
}
The above sequence is what I normally do for 'proper code'
To start with using a Messenger/EventAggregator can feel uncomfortable - it certainly took me a while to get used to it - but after I did get used to it, then I now use it everywhere - the pub/sub Message decoupling is very flexible for testing and for future maintenance of code (IMO)
As alternatives to this approach above I do sometimes take shortcuts:
sometimes I fire normal C# events from the ViewModel and have the View respond to these
sometimes I have special marker properties and fire the UI code from them
Sorry for using v3 syntax - but the changeover is coming and it's what I'm now coding in...
To switch back to vNext I think you might need to:
use IMessenger instead of IMvxMessenger
use BaseMessage instead of the MvxMessage
use Subscribe instead of SubscribeOnMainThread - but then you will need to marshall the message onto the UI thread yourself.
There exists an easier way. Here is the method I use for executing any action on the main
thread:
protected void RunOnUIThread(Action action) {
var dispatcher = Mvx.Resolve<IMvxMainThreadDispatcher>();
dispatcher.RequestMainThreadAction(action);
}
Hope it helps. Cheers.

Categories