1 // Copyright © 2017-2021 Rémi Thebault 2 module wayland.util; 3 4 import wayland.native.util; 5 6 /// Implemented by type that wrap a native wayland struct pointer. 7 interface Native(wl_native) 8 { 9 /// Access the wrapped struct. 10 @property inout(wl_native)* native() inout; 11 } 12 13 /// Utility mixin that implements Native for a type. 14 mixin template nativeImpl(wl_native) 15 { 16 private wl_native* _native; 17 18 public final override @property inout(wl_native)* native() inout 19 { 20 return _native; 21 } 22 } 23 24 25 immutable class WlInterface 26 { 27 private immutable wl_interface* _native; 28 29 immutable this(immutable wl_interface* native) 30 { 31 this._native = native; 32 } 33 34 @property immutable(wl_interface)* native() immutable 35 { 36 return _native; 37 } 38 39 @property string name() immutable 40 { 41 import std..string : fromStringz; 42 return fromStringz(_native.name); 43 } 44 } 45 46 /++ 47 + Check for equality between two interfaces 48 +/ 49 bool wlIfaceEquals(immutable(WlInterface) a, immutable(WlInterface) b) 50 { 51 import core.stdc..string : strcmp; 52 53 return a is b || strcmp(a._native.name, b._native.name) == 0; 54 } 55 56 /++ 57 + Wraps a function literal into a try-catch statement. 58 + 59 + Use this in functions called by C as exception cannot propagate there. 60 + The try-catch statement will print a warning if an exception is thrown. 61 + The try-catch statement will terminate runtime and exit program if an error is thrown. 62 +/ 63 auto nothrowFnWrapper(alias fn)() nothrow 64 { 65 try 66 { 67 return fn(); 68 } 69 catch(Exception ex) 70 { 71 import std.exception : collectException; 72 import std.stdio : stderr; 73 collectException(stderr.writeln("wayland-d: error in listener stub: "~ex.msg)); 74 } 75 catch(Throwable err) 76 { 77 import core.runtime : Runtime; 78 import core.stdc.stdlib : exit; 79 import std.exception : collectException; 80 import std.stdio : stderr; 81 collectException(stderr.writeln("wayland-d: aborting due to error in listener stub: "~err.msg)); 82 collectException(Runtime.terminate()); 83 exit(1); 84 } 85 alias rt = typeof(fn()); 86 static if (!is(rt == void)) 87 { 88 return rt.init; 89 } 90 } 91 92 93 94 /// static cache of objects that are looked-up by the address of their native 95 /// counter part 96 struct ObjectCache 97 { 98 private __gshared Object[void*] _cache; 99 100 static void set (void* native, Object obj) 101 { 102 _cache[native] = obj; 103 } 104 105 static Object get (void* native) 106 { 107 auto op = native in _cache; 108 return op ? *op : null; 109 } 110 111 static void remove (void* native) 112 { 113 _cache.remove(native); 114 } 115 } 116 117 /** 118 * Fixed-point number 119 * 120 * A `WlFixed` is a 24.8 signed fixed-point number with a sign bit, 23 bits 121 * of integer precision and 8 bits of decimal precision. 122 */ 123 struct WlFixed 124 { 125 private uint _raw; 126 private union DI 127 { 128 long i; 129 double d; 130 } 131 132 public this(uint raw) 133 { 134 _raw = raw; 135 } 136 137 /** 138 * Converts an integer to a fixed-point number. 139 */ 140 public static WlFixed create(in int val) 141 { 142 return WlFixed(val * 256); 143 } 144 145 /** 146 * Converts a floating-point number to a fixed-point number. 147 */ 148 public static WlFixed create(in double val) 149 { 150 DI u; 151 u.d = val + (3L << (51 - 8)); 152 return WlFixed(cast(uint)(u.i)); 153 } 154 155 @property uint raw() const 156 { 157 return _raw; 158 } 159 160 /** 161 * Converts a fixed-point number to an integer. 162 */ 163 int opCast(T : int)() const 164 { 165 return _raw / 256; 166 } 167 168 /** 169 * Converts a fixed-point number to a floating-point number. 170 */ 171 double opCast(T : double)() const 172 { 173 DI u; 174 u.i = ((1023L + 44L) << 52) + (1L << 51) + f; 175 return u.d - (3L << 43); 176 } 177 }