1 /+ 2 + Wayland copyright: 3 + Copyright © 2008 Kristian Høgsberg 4 + 5 + Permission is hereby granted, free of charge, to any person 6 + obtaining a copy of this software and associated documentation files 7 + (the "Software"), to deal in the Software without restriction, 8 + including without limitation the rights to use, copy, modify, merge, 9 + publish, distribute, sublicense, and/or sell copies of the Software, 10 + and to permit persons to whom the Software is furnished to do so, 11 + subject to the following conditions: 12 + 13 + The above copyright notice and this permission notice (including the 14 + next paragraph) shall be included in all copies or substantial 15 + portions of the Software. 16 + 17 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 21 + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 22 + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 + SOFTWARE. 25 +/ 26 /+ 27 + D bindings copyright: 28 + Copyright © 2015 Rémi Thebault 29 +/ 30 module wayland.client.util; 31 32 import wayland.client.opaque_types; 33 import std.range; 34 35 36 enum WAYLAND_VERSION_MAJOR = 1; 37 enum WAYLAND_VERSION_MINOR = 8; 38 enum WAYLAND_VERSION_MICRO = 90; 39 enum WAYLAND_VERSION = "1.8.90"; 40 41 42 43 extern (C) { 44 45 46 47 struct wl_message { 48 const (char*) name; 49 const (char*) signature; 50 const (wl_interface*)* types; 51 } 52 53 struct wl_interface { 54 const (char*) name; 55 int ver; 56 int method_count; 57 const (wl_message*) methods; 58 int event_count; 59 const (wl_message*) events; 60 } 61 62 /** \class wl_list 63 * 64 * \brief doubly-linked list 65 * 66 * The list head is of "struct wl_list" type, and must be initialized 67 * using wl_list_init(). All entries in the list must be of the same 68 * type. The item type must have a "struct wl_list" member. This 69 * member will be initialized by wl_list_insert(). There is no need to 70 * call wl_list_init() on the individual item. To query if the list is 71 * empty in O(1), use wl_list_empty(). 72 * 73 * Let's call the list reference "struct wl_list foo_list", the item type as 74 * "item_t", and the item member as "struct wl_list link". 75 * 76 * The following code will initialize a list: 77 * \code 78 * struct wl_list foo_list; 79 * 80 * struct item_t { 81 * int foo; 82 * struct wl_list link; 83 * }; 84 * struct item_t item1, item2, item3; 85 * 86 * wl_list_init(&foo_list); 87 * wl_list_insert(&foo_list, &item1.link); // Pushes item1 at the head 88 * wl_list_insert(&foo_list, &item2.link); // Pushes item2 at the head 89 * wl_list_insert(&item2.link, &item3.link); // Pushes item3 after item2 90 * \endcode 91 * 92 * The list now looks like [item2, item3, item1] 93 * 94 * Iterate the list in ascending order: 95 * \code 96 * item_t *item; 97 * wl_list_for_each(item, foo_list, link) { 98 * Do_something_with_item(item); 99 * } 100 * \endcode 101 */ 102 struct wl_list { 103 wl_list *prev; 104 wl_list *next; 105 } 106 107 108 109 struct wl_array { 110 size_t size; 111 size_t alloc; 112 void *data; 113 } 114 115 116 117 118 alias wl_fixed_t = int; 119 120 121 122 /** 123 * \brief A union representing all of the basic data types that can be passed 124 * along the wayland wire format. 125 * 126 * This union represents all of the basic data types that can be passed in the 127 * wayland wire format. It is used by dispatchers and runtime-friendly 128 * versions of the event and request marshaling functions. 129 */ 130 union wl_argument { 131 int i; /**< signed integer */ 132 uint u; /**< unsigned integer */ 133 wl_fixed_t f; /**< fixed point */ 134 const (char*) s; /**< string */ 135 wl_object *o; /**< object */ 136 uint n; /**< new_id */ 137 wl_array *a; /**< array */ 138 int h; /**< file descriptor */ 139 } 140 141 /** 142 * \brief A function pointer type for a dispatcher. 143 * 144 * A dispatcher is a function that handles the emitting of callbacks in client 145 * code. For programs directly using the C library, this is done by using 146 * libffi to call function pointers. When binding to languages other than C, 147 * dispatchers provide a way to abstract the function calling process to be 148 * friendlier to other function calling systems. 149 * 150 * A dispatcher takes five arguments: The first is the dispatcher-specific 151 * implementation data associated with the target object. The second is the 152 * object on which the callback is being invoked (either wl_proxy or 153 * wl_resource). The third and fourth arguments are the opcode the wl_messsage 154 * structure corresponding to the callback being emitted. The final argument 155 * is an array of arguments received from the other process via the wire 156 * protocol. 157 */ 158 alias wl_dispatcher_func_t = int function (const (void*), void*, uint, 159 const (wl_message*), wl_argument*); 160 161 alias wl_log_func_t = void function (const (char*), ...); 162 163 } 164 165 /** 166 * Retrieves a pointer to the containing struct of a given member item. 167 * 168 * This macro allows conversion from a pointer to a item to its containing 169 * struct. This is useful if you have a contained item like a wl_list, 170 * wl_listener, or wl_signal, provided via a callback or other means and would 171 * like to retrieve the struct that contains it. 172 * 173 * To demonstrate, the following example retrieves a pointer to 174 * `example_container` given only its `destroy_listener` member: 175 * 176 * \code 177 * struct example_container { 178 * struct wl_listener destroy_listener; 179 * // other members... 180 * }; 181 * 182 * void example_container_destroy(struct wl_listener *listener, void *data) 183 * { 184 * struct example_container *ctr; 185 * 186 * ctr = wl_container_of(listener, ctr, destroy_listener); 187 * // destroy ctr... 188 * } 189 * \endcode 190 * 191 * \param ptr A valid pointer to the contained item. 192 * 193 * \param sample A pointer to the type of content that the list item 194 * stores. Sample does not need be a valid pointer; a null or 195 * an uninitialised pointer will suffice. 196 * 197 * \param member The named location of ptr within the sample type. 198 * 199 * \return The container for the specified pointer. 200 */ 201 template wl_container_of(alias member) 202 { 203 static ParentOf!member* wl_container_of(T)(T* ptr) 204 { 205 return cast(ParentOf!member*)(cast(ptrdiff_t)(ptr)-member.offsetof); 206 } 207 } 208 209 unittest { 210 211 struct S { 212 string foo; 213 int bar; 214 } 215 216 S s; 217 assert(wl_container_of!(S.bar)(&s.bar) == &s); 218 } 219 220 221 template wl_range(alias member) 222 { 223 static WlListRange!member wl_range(wl_list *head) 224 { 225 return WlListRange!member(head); 226 } 227 } 228 229 unittest 230 { 231 struct Item 232 { 233 int num; 234 wl_list link; 235 236 this(int num) { this.num = num; } 237 } 238 auto i1 = Item(1); 239 auto i2 = Item(2); 240 auto i3 = Item(3); 241 242 wl_list lst; 243 wl_list_init(&lst); 244 wl_list_insert(&lst, &i1.link); 245 wl_list_insert(&lst, &i2.link); 246 wl_list_insert(&i2.link, &i3.link); 247 248 int[] forw_arr; 249 foreach(it; wl_range!(Item.link)(&lst)) { 250 forw_arr ~= it.num; 251 } 252 assert(forw_arr == [2, 3, 1]); 253 254 int[] back_arr; 255 foreach_reverse(it; wl_range!(Item.link)(&lst)) { 256 back_arr ~= it.num; 257 } 258 assert(back_arr == [1, 3, 2]); 259 } 260 261 262 263 264 template wl_range(T) 265 { 266 static WlArrayRange!T wl_range(wl_array *arr) 267 { 268 return WlArrayRange!T(arr); 269 } 270 } 271 272 unittest 273 { 274 wl_array arr; 275 wl_array_init(&arr); 276 277 foreach(i; 0..1342) { 278 int *ptr = cast(int*)wl_array_add(&arr, int.sizeof); 279 *ptr = i*12 - 15; 280 281 } 282 283 int ind=0; 284 foreach(pi; wl_range!(int)(&arr)) { 285 assert(*pi == ind++*12-15); 286 } 287 assert(ind==1342); 288 289 wl_array_release(&arr); 290 } 291 292 293 294 double 295 wl_fixed_to_double (wl_fixed_t f) 296 { 297 union di { 298 double d; 299 long i; 300 } 301 di u; 302 303 u.i = ((1023L + 44L) << 52) + (1L << 51) + f; 304 305 return u.d - (3L << 43); 306 } 307 308 wl_fixed_t 309 wl_fixed_from_double(double d) 310 { 311 union di { 312 double d; 313 long i; 314 } 315 di u; 316 317 u.d = d + (3L << (51 - 8)); 318 319 return cast(wl_fixed_t)u.i; 320 } 321 322 int wl_fixed_to_int(wl_fixed_t f) 323 { 324 return f / 256; 325 } 326 wl_fixed_t wl_fixed_from_int(int i) 327 { 328 return i * 256; 329 } 330 331 332 333 334 private { 335 336 template Id(alias a) { alias Id = a; } 337 338 339 template ParentOf(alias member) 340 { 341 alias ParentOf = Id!(__traits(parent, member)); 342 } 343 344 struct WlListRange(alias member) 345 { 346 wl_list *head; 347 wl_list *fpos; 348 wl_list *bpos; 349 350 alias ElType = ParentOf!member; 351 352 this(wl_list *head) 353 { 354 this.head = head; 355 fpos = head.next; 356 bpos = head.prev; 357 } 358 359 // input 360 361 @property bool empty() const { 362 return fpos == head || bpos == head; 363 } 364 365 @property ElType *front() { 366 return wl_container_of!member(fpos); 367 } 368 369 void popFront() { 370 fpos = fpos.next; 371 } 372 373 // forward 374 375 @property WlListRange!member save() { 376 return this; 377 } 378 379 // bidirectional 380 381 @property ElType *back() { 382 return wl_container_of!member(bpos); 383 } 384 385 void popBack() { 386 bpos = bpos.prev; 387 } 388 } 389 390 391 struct Item 392 { 393 int num; 394 wl_list link; 395 396 this(int num) { this.num = num; } 397 } 398 399 static assert(isBidirectionalRange!(WlListRange!(Item.link))); 400 401 402 struct WlArrayRange(T) 403 { 404 wl_array *arr; 405 size_t fpos; 406 size_t bpos; 407 408 this (wl_array *arr) 409 { 410 assert(arr.size % T.sizeof == 0); 411 this.arr = arr; 412 fpos = 0; 413 bpos = arr.size / T.sizeof; 414 } 415 416 // input 417 418 @property bool empty() const { 419 return fpos == arr.size / T.sizeof || bpos == 0; 420 } 421 422 @property inout(T)* front() inout { 423 return cast(inout(T)*)(arr.data + fpos*T.sizeof); 424 } 425 426 void popFront() { 427 ++fpos; 428 } 429 430 431 // forward 432 433 @property WlArrayRange!T save() { 434 return this; 435 } 436 437 438 // bidirectional 439 440 @property inout(T)* back() inout { 441 return cast(inout(T)*)(arr.data + bpos*T.sizeof); 442 } 443 444 void popBack() { 445 --bpos; 446 } 447 448 449 // random access 450 451 @property size_t length() const { 452 return arr.size / T.sizeof; 453 } 454 455 inout(T)* opIndex(size_t n) inout { 456 return cast(inout(T)*)(arr.data + n*T.sizeof); 457 } 458 459 } 460 461 static assert(isRandomAccessRange!(WlArrayRange!int)); 462 463 464 } 465 466 467 version (Dynamic) { 468 extern (C) { 469 alias da_wl_list_init = void function (wl_list *list); 470 alias da_wl_list_insert = void function (wl_list *list, wl_list *elm); 471 alias da_wl_list_remove = void function (wl_list *elm); 472 alias da_wl_list_length = int function (const (wl_list*) list); 473 alias da_wl_list_empty = int function (const (wl_list*) list); 474 alias da_wl_list_insert_list = void function (wl_list *list, wl_list *other); 475 476 alias da_wl_array_init = void function (wl_array *array); 477 alias da_wl_array_release = void function (wl_array *array); 478 alias da_wl_array_add = void *function (wl_array *array, size_t size); 479 alias da_wl_array_copy = int function (wl_array *array, wl_array *source); 480 } 481 __gshared { 482 483 da_wl_list_init wl_list_init; 484 da_wl_list_insert wl_list_insert; 485 da_wl_list_remove wl_list_remove; 486 da_wl_list_length wl_list_length; 487 da_wl_list_empty wl_list_empty; 488 da_wl_list_insert_list wl_list_insert_list; 489 490 da_wl_array_init wl_array_init; 491 da_wl_array_release wl_array_release; 492 da_wl_array_add wl_array_add; 493 da_wl_array_copy wl_array_copy; 494 } 495 496 } 497 else { 498 extern (C) { 499 void wl_list_init (wl_list *list); 500 void wl_list_insert (wl_list *list, wl_list *elm); 501 void wl_list_remove (wl_list *elm); 502 int wl_list_length (const (wl_list*) list); 503 int wl_list_empty (const (wl_list*) list); 504 void wl_list_insert_list (wl_list *list, wl_list *other); 505 506 void wl_array_init (wl_array *array); 507 void wl_array_release (wl_array *array); 508 void * wl_array_add (wl_array *array, size_t size); 509 int wl_array_copy (wl_array *array, wl_array *source); 510 } 511 } 512 513 514