1 /++ 2 A module for connecting to the window manager and also loading the necessary 3 libraries, everything that does runtime, to which other objects can access 4 the necessary objects. 5 6 $(LREF runtime) Gives access to runtime. Before that, you need to initialize the 7 runtime with the $(HREF runtime/ITidaRuntime.initialize,ITidaRuntime.initialize) 8 function if it has not been initialized earlier. 9 10 The easiest way to initialize: 11 --- 12 void main(string[] args) { 13 TidaRuntime.initialize(args); 14 ... 15 } 16 --- 17 18 Macros: 19 LREF = <a href="#$1">$1</a> 20 HREF = <a href="$1">$2</a> 21 22 Authors: $(HREF https://github.com/TodNaz,TodNaz) 23 Copyright: Copyright (c) 2020 - 2021, TodNaz. 24 License: $(HREF https://github.com/TodNaz/Tida/blob/master/LICENSE,MIT) 25 +/ 26 module tida.runtime; 27 28 __gshared TidaRuntime _runtimeObject; 29 30 /++ 31 Global access to runtime. An object can be called from anywhere, 32 but cannot be replaced. 33 +/ 34 @property TidaRuntime runtime() @trusted 35 { 36 return _runtimeObject; 37 } 38 39 enum : int 40 { 41 OpenAL = 0, /// Open Audio Library 42 FreeType, /// Free Type Library 43 GLX, /// Graphics library X11 44 EGL /// EGL library wayland 45 } 46 47 alias LibraryUnite = int; /// 48 49 enum AllLibrary = [OpenAL, FreeType, GLX]; 50 enum WithoutLibrary = [GLX]; 51 52 /++ 53 The interface of interaction between the program and the window manager. 54 +/ 55 interface ITidaRuntime 56 { 57 @safe: 58 /++ 59 A function for loading external libraries that are needed when implementing 60 internal functions. 61 62 Params: 63 libs = What external libraries need to be loaded. 64 (allLibrary to load all external libraries, 65 WithoutLibrary in order not to load unnecessary 66 external libraries.) 67 68 Throws: 69 $(OBJECTREF Exception) If the libraries were not installed on the machine 70 being started or they were damaged. 71 +/ 72 void loadExternalLibraries(LibraryUnite[] libs); 73 74 /++ 75 Connects to the window manager. 76 77 Throws: 78 $(OBJECTREF Exception) If the libraries were not installed on the machine 79 being started or they were damaged. And also if the connection to the 80 window manager was not successful (for example, there is no such component 81 in the OS or the connection to an unknown window manager is not supported). 82 +/ 83 void connectToWndMng(); 84 85 /++ 86 Closes the session with the window manager. 87 +/ 88 void closeWndMngSession(); 89 90 /++ 91 Arguments given to the program. 92 +/ 93 @property string[] mainArguments(); 94 95 /++ 96 Accepts program arguments for subsequent operations with them. 97 +/ 98 void acceptArguments(string[] arguments); 99 100 @trusted: 101 /++ 102 Runtime initialization. It includes such stages as: 103 1. Loading external libraries. 104 2. Connection to the window manager. 105 3. Preparation of objects for work. 106 107 Params: 108 arguments = Arguments given to the program. 109 libs = What external libraries need to be loaded. 110 (allLibrary to load all external libraries, 111 WithoutLibrary in order not to load unnecessary 112 external libraries.) 113 114 Throws: 115 $(OBJECTREF Exception) If the libraries were not installed on the machine 116 being started or they were damaged. And also if the connection to the 117 window manager was not successful (for example, there is no such 118 component in the OS or the connection to an unknown window manager 119 is not supported). 120 +/ 121 static final void initialize( string[] arguments = [], 122 LibraryUnite[] libs = AllLibrary) 123 { 124 _runtimeObject = new TidaRuntime(); 125 _runtimeObject.acceptArguments(arguments); 126 _runtimeObject.loadExternalLibraries(libs); 127 _runtimeObject.connectToWndMng(); 128 } 129 } 130 131 /++ 132 The interface of interaction between the program and the window manager. 133 +/ 134 version (Posix) 135 class TidaRuntime : ITidaRuntime 136 { 137 import x11.X, x11.Xlib, x11.Xutil; 138 import std.exception : enforce; 139 import tida.sound : initSoundlibrary, Device; 140 import tida.text : initFontLibrary; 141 142 enum SessionType 143 { 144 unknown, 145 x11, 146 wayland 147 } 148 149 enum SessionWarning = 150 "WARNING! The session is not defined. Perhaps she simply does not exist?"; 151 152 private: 153 Display* _display; 154 int _displayID; 155 string[] arguments; 156 SessionType _session; 157 Device _device; 158 159 public @trusted: 160 this() 161 { 162 import std.process; 163 import std.stdio : stderr, writeln; 164 165 auto env = environment.get("XDG_SESSION_TYPE"); 166 if (env == "x11") 167 { 168 _session = SessionType.x11; 169 } else 170 if (env == "wayland") 171 { 172 _session = SessionType.wayland; 173 } else 174 { 175 _session = SessionType.unknown; 176 stderr.writeln(SessionWarning); 177 } 178 179 } 180 181 override void loadExternalLibraries(LibraryUnite[] libs) 182 { 183 import dglx.glx : loadGLXLibrary; 184 185 foreach (e; libs) 186 { 187 if (e == OpenAL) 188 { 189 initSoundlibrary(); 190 _device = new Device(); 191 _device.open(); 192 } 193 else 194 if (e == FreeType) 195 initFontLibrary(); 196 else 197 if (e == GLX) { 198 if (_session == SessionType.x11) 199 loadGLXLibrary(); 200 } 201 } 202 } 203 204 override void connectToWndMng() 205 { 206 this._display = XOpenDisplay(null); 207 enforce!Exception(this._display, 208 "Failed to connect to window manager."); 209 210 this._displayID = DefaultScreen(this._display); 211 } 212 213 override void closeWndMngSession() 214 { 215 XCloseDisplay(this._display); 216 this._display = null; 217 this._displayID = 0; 218 } 219 220 override void acceptArguments(string[] arguments) 221 { 222 this.arguments = arguments; 223 } 224 225 @property override string[] mainArguments() 226 { 227 return this.arguments; 228 } 229 230 @property Window rootWindow() 231 { 232 return RootWindow(_display, _displayID); 233 } 234 @safe: 235 /// An instance for contacting the manager's server. 236 @property Display* display() 237 { 238 return this._display; 239 } 240 241 /// Default screen number 242 @property int displayID() 243 { 244 return this._displayID; 245 } 246 247 ~this() 248 { 249 closeWndMngSession(); 250 } 251 } 252 253 version(Windows) 254 class TidaRuntime : ITidaRuntime 255 { 256 import core.sys.windows.windows; 257 import std.exception : enforce; 258 import tida.sound : initSoundlibrary, Device; 259 import tida.text : initFontLibrary; 260 261 private: 262 HINSTANCE hInstance; 263 string[] arguments; 264 Device _device; 265 266 public @trusted: 267 override void loadExternalLibraries(LibraryUnite[] libs) 268 { 269 foreach (e; libs) 270 { 271 if (e == OpenAL) 272 { 273 initSoundlibrary(); 274 _device = new Device(); 275 _device.open(); 276 } 277 else 278 if (e == FreeType) 279 initFontLibrary(); 280 } 281 } 282 283 override void connectToWndMng() 284 { 285 this.hInstance = GetModuleHandle(null); 286 debug {} else 287 ShowWindow(GetConsoleWindow(), SW_HIDE); 288 289 enforce!Exception(this.hInstance, 290 "Failed to connect to window manager."); 291 } 292 293 override void closeWndMngSession() 294 { 295 this.hInstance = null; 296 } 297 298 override void acceptArguments(string[] arguments) 299 { 300 this.arguments = arguments; 301 } 302 303 @property override string[] mainArguments() 304 { 305 return this.arguments; 306 } 307 308 @safe: 309 @property HINSTANCE instance() 310 { 311 return this.hInstance; 312 } 313 }