summaryrefslogtreecommitdiff
path: root/src/bindings/mono/efl_mono/efl_all.cs
blob: de917a3e686fb568643f83cd012bb271c86f2aac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#pragma warning disable 1591

using System;
using System.Runtime.InteropServices;
using System.Threading;

using static Efl.UnsafeNativeMethods;

namespace Efl
{

static class UnsafeNativeMethods
{
    private delegate void init_func_delegate();
    [DllImport(efl.Libs.Ecore)] internal static extern void ecore_init();
    [DllImport(efl.Libs.Ecore)] internal static extern void ecore_init_ex(int argc, IntPtr argv);
    [DllImport(efl.Libs.Ecore)] internal static extern void ecore_shutdown();
    // dotnet loads libraries from DllImport with RTLD_LOCAL. Due to the
    // way evas modules are built with meson, currently they do not link directly
    // with libevas, leading to symbol not found errors when trying to open them.
    // The call to FunctionWrapper makes sure evas is loaded with RTLD_GLOBAL,
    // allowing the symbols to remain visible for the modules until the build
    // is sorted out.
    private static Efl.Eo.FunctionWrapper<init_func_delegate> _evas_init;
    [DllImport(efl.Libs.Evas)] internal static extern void evas_shutdown();
    [DllImport(efl.Libs.Elementary)] internal static extern int elm_init(int argc, IntPtr argv);
    [DllImport(efl.Libs.Elementary)] internal static extern void elm_shutdown();
    [DllImport(efl.Libs.Elementary)] internal static extern void elm_run();
    [DllImport(efl.Libs.Elementary)] internal static extern void elm_exit();

    static UnsafeNativeMethods()
    {
        _evas_init = new Efl.Eo.FunctionWrapper<init_func_delegate>(efl.Libs.Evas, "evas_init");
    }

    internal static void evas_init()
    {
        _evas_init.Value.Delegate();
    }
}

/// <summary>Wrapper around the initialization functions of all modules.
/// <para>Since EFL 1.23.</para>
/// </summary>
public static class All
{
    private static bool InitializedUi = false;

    /// <summary>
    ///   If the main loop was initialized.
    /// <para>Since EFL 1.23.</para>
    /// </summary>
    public static bool MainLoopInitialized {
        get;
        private set;
    }

    internal static readonly object InitLock = new object();

    /// <summary>
    ///   Initialize the Efl.
    /// <para>Since EFL 1.23.</para>
    /// </summary>
    /// <param name="components">The <see cref="Efl.Csharp.Components" /> that initialize the Efl.</param>
    public static void Init(Efl.Csharp.Components components = Efl.Csharp.Components.Basic)
    {
        Eina.Config.Init();
        Efl.Eo.Config.Init();
        ecore_init();
        ecore_init_ex(0, IntPtr.Zero);
        evas_init();
        eldbus.Config.Init();

        if (components == Efl.Csharp.Components.Ui)
        {
            Efl.Ui.Config.Init();
            InitializedUi = true;
        }
        Monitor.Enter(InitLock);
        MainLoopInitialized = true;
        Monitor.Exit(InitLock);
    }

    /// <summary>Shutdowns all EFL subsystems.
    /// <para>Since EFL 1.23.</para>
    /// </summary>
    public static void Shutdown()
    {
        // Try to cleanup everything before actually shutting down.
        Eina.Log.Debug("Calling GC before shutdown");
        for (int i = 0; i < 3; i++)
        {
            System.GC.Collect();
            System.GC.WaitForPendingFinalizers();
            Efl.App.AppMain.Iterate();
        }

        Monitor.Enter(InitLock);
        MainLoopInitialized = false;
        Monitor.Exit(InitLock);

        if (InitializedUi)
        {
            Eina.Log.Debug("Shutting down Elementary");
            Efl.Ui.Config.Shutdown();
        }

        Eina.Log.Debug("Shutting down Eldbus");
        eldbus.Config.Shutdown();
        Eina.Log.Debug("Shutting down Evas");
        evas_shutdown();
        Eina.Log.Debug("Shutting down Ecore");
        ecore_shutdown();
        Eina.Log.Debug("Shutting down Eo");
        Efl.Eo.Config.Shutdown();
        Eina.Log.Debug("Shutting down Eina");
        Eina.Config.Shutdown();
    }
}

// Placeholder. Will move to elm_config.cs later
namespace Ui
{

/// <summary>Initialization and shutdown of the UI libraries.
/// <para>Since EFL 1.23.</para>
/// </summary>
public static class Config
{
    /// <summary>
    /// Initialize the configuration of Elm.
    /// <para>Since EFL 1.23.</para>
    /// </summary>
    public static void Init()
    {
        // TODO Support elm command line arguments
#if WIN32 // Not a native define, we define it in our build system
        // Ecore_Win32 uses OleInitialize, which requires single thread apartments
        if (System.Threading.Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
        {
            throw new InvalidOperationException("UI Applications require STAThreadAttribute in Main()");
        }
#endif
        elm_init(0, IntPtr.Zero);

        Efl.Ui.Win.ExitOnAllWindowsClosed = new Eina.Value(0);
    }

    /// <summary>
    ///   Shutdown Elm systems.
    /// <para>Since EFL 1.24.</para>
    /// </summary>
    public static void Shutdown()
    {
        elm_shutdown();
    }

    /// <summary>
    ///   Run Elm system.
    /// <para>Since EFL 1.23.</para>
    /// </summary>
    public static void Run()
    {
        elm_run();
    }

    /// <summary>
    ///   Exit Elm.
    /// <para>Since EFL 1.23.</para>
    /// </summary>
    public static void Exit()
    {
        elm_exit();
    }
}

}

}