PageRenderTime 48ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/wrap_xlib.c

http://github.com/dmsh/ocaml-xlib
C | 6005 lines | 4981 code | 580 blank | 444 comment | 189 complexity | 005a9d9d38f67392377279f7cc79fa41 MD5 | raw file
  1. /* OCaml bindings for the Xlib library.
  2. * Copyright (C) 2008, 2009, 2010 by Florent Monnier
  3. * Contact: <fmonnier@linux-nantes.org>
  4. *
  5. * OCaml-Xlib is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Lesser General Public License as published
  7. * by the Free Software Foundation, either version 3 of the License,
  8. * or (at your option) any later version.
  9. *
  10. * OCaml-Xlib is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public License
  16. * along with OCaml-Xlib. If not, see:
  17. * <http://www.gnu.org/licenses/>
  18. */
  19. // {{{ Headers
  20. #include <X11/Xlib.h>
  21. #include <X11/Xutil.h>
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #define CAML_NAME_SPACE 1
  26. #include <caml/mlvalues.h>
  27. #include <caml/memory.h>
  28. #include <caml/alloc.h>
  29. #include <caml/bigarray.h>
  30. #include <caml/custom.h>
  31. #include <caml/fail.h>
  32. #include <caml/callback.h>
  33. // }}}
  34. #include "wrap_xlib.h"
  35. // {{{ caml allocs
  36. custom_ops(XEvent);
  37. custom_ops(XColor);
  38. custom_ops(XGCValues);
  39. custom_ops(XSetWindowAttributes);
  40. custom_ops(XWindowAttributes);
  41. custom_ops(XSizeHints);
  42. custom_ops(XVisualInfo);
  43. custom_ops(XChar2b);
  44. custom_ops_n(XChar2b);
  45. // }}}
  46. // {{{ XID's
  47. #define Drawable_val(v) (XID_val(Drawable,(v)))
  48. #define Val_Drawable(xid) (Val_XID((xid)))
  49. #define Cursor_val(v) (XID_val(Cursor,(v)))
  50. #define Val_Cursor(xid) (Val_XID((xid)))
  51. #define Colormap_val(v) (XID_val(Colormap,(v)))
  52. #define Val_Colormap(xid) (Val_XID((xid)))
  53. #define GContext_val(v) (XID_val(GContext,(v)))
  54. #define Val_GContext(xid) (Val_XID((xid)))
  55. //#define KeySym_val(v) (XID_val(KeySym,(v)))
  56. //#define Val_KeySym(xid) (Val_XID((xid)))
  57. /* Get keysyms values instead of an abstract type */
  58. #define Val_keysym Val_int
  59. #define Keysym_val Long_val
  60. // }}}
  61. // {{{ return status
  62. #define DO_CHECK_RETURN_STATUS 1
  63. #if DO_CHECK_RETURN_STATUS
  64. #define GET_STATUS int status =
  65. #define CHECK_STATUS(fun,st) \
  66. do{ if (status != st) caml_failwith(#fun ": wrong return status"); }while(0)
  67. #else
  68. #define GET_STATUS (void)
  69. #define CHECK_STATUS
  70. #endif
  71. /* Many GET/CHECK STATUS are commented just because in
  72. * the source code of the Xlib implementation I use (XOrg)
  73. * the return status is just static and can only return one
  74. * value, so testing it is meaningless.
  75. * They are kept commented in case they are meaningfull in
  76. * an other implementation.
  77. *
  78. * Sometime the return value meaning a success is 1 and sometime 0,
  79. * even in the commented GET/CHECK_STATUS the value is the good one.
  80. */
  81. // }}}
  82. // {{{ GC
  83. // Handle the finalisation of GC's (other than the default one)
  84. #define GC_val(gc_pair) ((GC) Field((gc_pair),0))
  85. #define Display_of_GC(gc_pair) (Field((gc_pair),1))
  86. void Finalize_GC( value gc )
  87. {
  88. value dpy = Display_of_GC(gc);
  89. if (display_is_open(dpy)) {
  90. GET_STATUS XFreeGC(
  91. Display_val(dpy),
  92. GC_val(gc)
  93. );
  94. CHECK_STATUS(XFreeGC,1);
  95. }
  96. }
  97. CAMLprim value do_finalize_GC( value gc ) {
  98. Finalize_GC( gc );
  99. return Val_unit;
  100. }
  101. /*
  102. static struct custom_operations fgc_custom_ops = {
  103. identifier: "GC handling",
  104. finalize: Finalize_GC,
  105. compare: custom_compare_default,
  106. hash: custom_hash_default,
  107. serialize: custom_serialize_default,
  108. deserialize: custom_deserialize_default
  109. };
  110. */
  111. // The finalised one
  112. static inline value Val_GC_final(GC gc, value dpy)
  113. {
  114. CAMLparam1( dpy );
  115. CAMLlocal1( fgc );
  116. //fgc = caml_alloc_custom( &fgc_custom_ops, 2 * sizeof(value), 0, 1);
  117. // the previous line segfaults
  118. // so the link is done with do_finalize_GC from the ocaml side
  119. fgc = caml_alloc(2, 0);
  120. Store_field( fgc, 0, ((value)(gc)) );
  121. Store_field( fgc, 1, dpy );
  122. CAMLreturn( fgc );
  123. }
  124. // Not finalised (for default gc)
  125. static inline value Val_GC(GC gc, value dpy)
  126. {
  127. CAMLparam1( dpy );
  128. CAMLlocal1( gcp );
  129. gcp = caml_alloc(2, 0);
  130. Store_field( gcp, 0, ((value)(gc)) );
  131. Store_field( gcp, 1, dpy );
  132. CAMLreturn( gcp );
  133. }
  134. // }}}
  135. // {{{ Event-Masks
  136. static const long event_mask_table[] = {
  137. KeyPressMask,
  138. KeyReleaseMask,
  139. ButtonPressMask,
  140. ButtonReleaseMask,
  141. EnterWindowMask,
  142. LeaveWindowMask,
  143. PointerMotionMask,
  144. PointerMotionHintMask,
  145. Button1MotionMask,
  146. Button2MotionMask,
  147. Button3MotionMask,
  148. Button4MotionMask,
  149. Button5MotionMask,
  150. ButtonMotionMask,
  151. KeymapStateMask,
  152. ExposureMask,
  153. VisibilityChangeMask,
  154. StructureNotifyMask,
  155. ResizeRedirectMask,
  156. SubstructureNotifyMask,
  157. SubstructureRedirectMask,
  158. FocusChangeMask,
  159. PropertyChangeMask,
  160. ColormapChangeMask,
  161. OwnerGrabButtonMask,
  162. };
  163. static inline long
  164. Eventmask_val( value em_list )
  165. {
  166. long event_mask = 0;
  167. while ( em_list != Val_emptylist )
  168. {
  169. value head = Field(em_list, 0);
  170. long mask = event_mask_table[Long_val(head)];
  171. event_mask |= mask;
  172. em_list = Field(em_list, 1);
  173. }
  174. return event_mask;
  175. }
  176. // }}}
  177. // {{{ macro/funcs
  178. /* switch this to use the macros or the functions */
  179. //#define XMP(f) X##f // use the functions
  180. #define XMP(f) f // use the macros
  181. #define _xConnectionNumber XMP(ConnectionNumber)
  182. #define _xRootWindow XMP(RootWindow)
  183. #define _xDefaultScreen XMP(DefaultScreen)
  184. #define _xDefaultRootWindow XMP(DefaultRootWindow)
  185. #define _xDefaultVisual XMP(DefaultVisual)
  186. #define _xDefaultGC XMP(DefaultGC)
  187. #define _xBlackPixel XMP(BlackPixel)
  188. #define _xWhitePixel XMP(WhitePixel)
  189. #define _xDisplayWidth XMP(DisplayWidth)
  190. #define _xDisplayHeight XMP(DisplayHeight)
  191. #define _xDisplayPlanes XMP(DisplayPlanes)
  192. #define _xDisplayCells XMP(DisplayCells)
  193. #define _xScreenCount XMP(ScreenCount)
  194. #define _xServerVendor XMP(ServerVendor)
  195. #define _xProtocolVersion XMP(ProtocolVersion)
  196. #define _xProtocolRevision XMP(ProtocolRevision)
  197. #define _xVendorRelease XMP(VendorRelease)
  198. #define _xDisplayString XMP(DisplayString)
  199. #define _xDefaultDepth XMP(DefaultDepth)
  200. #define _xDefaultColormap XMP(DefaultColormap)
  201. #define _xBitmapUnit XMP(BitmapUnit)
  202. #define _xBitmapBitOrder XMP(BitmapBitOrder)
  203. #define _xBitmapPad XMP(BitmapPad)
  204. #define _xImageByteOrder XMP(ImageByteOrder)
  205. #define _xBitmapUnit XMP(BitmapUnit)
  206. #define _xScreenOfDisplay XMP(ScreenOfDisplay)
  207. #define _xDefaultScreenOfDisplay XMP(DefaultScreenOfDisplay)
  208. #define _xDisplayOfScreen XMP(DisplayOfScreen)
  209. #define _xRootWindowOfScreen XMP(RootWindowOfScreen)
  210. #define _xBlackPixelOfScreen XMP(BlackPixelOfScreen)
  211. #define _xWhitePixelOfScreen XMP(WhitePixelOfScreen)
  212. #define _xDefaultColormapOfScreen XMP(DefaultColormapOfScreen)
  213. #define _xDefaultDepthOfScreen XMP(DefaultDepthOfScreen)
  214. #define _xDefaultGCOfScreen XMP(DefaultGCOfScreen)
  215. #define _xDefaultVisualOfScreen XMP(DefaultVisualOfScreen)
  216. #define _xWidthOfScreen XMP(WidthOfScreen)
  217. #define _xHeightOfScreen XMP(HeightOfScreen)
  218. #define _xWidthMMOfScreen XMP(WidthMMOfScreen)
  219. #define _xHeightMMOfScreen XMP(HeightMMOfScreen)
  220. #define _xPlanesOfScreen XMP(PlanesOfScreen)
  221. #define _xCellsOfScreen XMP(CellsOfScreen)
  222. #define _xMinCmapsOfScreen XMP(MinCmapsOfScreen)
  223. #define _xMaxCmapsOfScreen XMP(MaxCmapsOfScreen)
  224. #define _xDoesSaveUnders XMP(DoesSaveUnders)
  225. #define _xDoesBackingStore XMP(DoesBackingStore)
  226. #define _xEventMaskOfScreen XMP(EventMaskOfScreen)
  227. // }}}
  228. // {{{ ints
  229. // wraps unsigned long
  230. #define Pixel_color_val Unsigned_long_val
  231. #define Val_pixel_color Val_long
  232. // type 'Time' defined in X.h (unsigned long / CARD32)
  233. // use int64 instead of int32 because the max value of unsigned is twice
  234. // (ocaml int32 is signed)
  235. #define Val_time caml_copy_int64
  236. #define Time_val(t) ((Time)Int64_val(t))
  237. // same value than Int64.max_int (used to check Time overflow)
  238. // (not used anymore, while CARD32 can not overflow a signed int64)
  239. #define MAX_INT64 9223372036854775807L
  240. // }}}
  241. // {{{ Atom
  242. #define Val_Atom(v) ((value)(v))
  243. #define Atom_val(v) ((Atom)(v))
  244. #define Atom_val_addr(v) ((Atom *)(&v))
  245. // }}}
  246. // {{{ KeyCode
  247. /* There's no real uniformity about the type keycode,
  248. - in structures it is most often (int) and sometimes (unsigned int)
  249. - in functions sometimes there is the NeedWidePrototypes switch
  250. which switches between (unsigned int) and (unsigned char)
  251. - in functions sometimes it is just (int) as parameter
  252. or (int *) if it's a returned value
  253. However as it handles a code for each key of the keyboard, and that generally
  254. keyboards have about 105 keys, it seems that it does not really matter.
  255. */
  256. #define Val_KeyCode Val_long
  257. #define KeyCode_val Long_val
  258. // }}}
  259. // {{{ caml_copy_string_array_n()
  260. // The list provided to caml_copy_string_array() needs to be NULL terminated
  261. static value caml_copy_string_array_n(char **strl, int n)
  262. {
  263. CAMLlocal1(ret);
  264. char const **param;
  265. int i;
  266. param = malloc((n+1) * sizeof(char *));
  267. for (i=0; i<n; i++) {
  268. param[i] = strl[i];
  269. }
  270. param[n] = NULL; // here the point
  271. ret = caml_copy_string_array(param);
  272. free(param);
  273. return ret;
  274. }
  275. // }}}
  276. // TODO: XGetErrorText()
  277. #if 0
  278. int ErrorHandler( Display *dpy, XErrorEvent *event )
  279. {
  280. char buffer[BUFSIZ];
  281. XGetErrorText(dpy, event->error_code, buffer, BUFSIZ);
  282. /*
  283. event->request_code;
  284. event->minor_code;
  285. event->resourceid;
  286. event->serial;
  287. */
  288. printf("ERROR: %s\n", buffer);
  289. return 0;
  290. }
  291. CAMLprim value
  292. ml_XSetErrorHandler( value unit )
  293. {
  294. XSetErrorHandler( ErrorHandler );
  295. return Val_unit;
  296. }
  297. #endif
  298. int ErrorHandler_closure( Display *dpy, XErrorEvent *event )
  299. {
  300. CAMLlocal1( ml_event );
  301. static value * closure_f = NULL;
  302. if (closure_f == NULL) {
  303. closure_f = caml_named_value("Error Handler Callback");
  304. }
  305. copy_XEvent( event, ml_event );
  306. caml_callback2( *closure_f, Val_Display(dpy), ml_event );
  307. return 0;
  308. }
  309. CAMLprim value
  310. ml_XSetErrorHandler( value unit ) {
  311. XSetErrorHandler(ErrorHandler_closure);
  312. return Val_unit;
  313. }
  314. CAMLprim value
  315. ml_XlibSpecificationRelease( value unit )
  316. {
  317. return Val_int(XlibSpecificationRelease);
  318. }
  319. CAMLprim value
  320. ml_XOpenDisplay( value display_name )
  321. {
  322. Display *dpy;
  323. dpy = XOpenDisplay( String_val(display_name) );
  324. if (dpy == NULL) {
  325. caml_failwith("Cannot open display");
  326. }
  327. return Val_Display(dpy);
  328. }
  329. CAMLprim value
  330. ml_XCloseDisplay( value dpy )
  331. {
  332. XCloseDisplay( Display_val(dpy) );
  333. display_record_closed(dpy);
  334. return Val_unit;
  335. }
  336. CAMLprim value
  337. ml_XFlush( value dpy )
  338. {
  339. GET_STATUS XFlush( Display_val(dpy) );
  340. CHECK_STATUS(XFlush, 1);
  341. return Val_unit;
  342. }
  343. CAMLprim value
  344. ml_XBell( value dpy, value percent )
  345. {
  346. //GET_STATUS
  347. XBell(
  348. Display_val(dpy),
  349. Int_val(percent)
  350. );
  351. //CHECK_STATUS(XBell,1);
  352. return Val_unit;
  353. }
  354. static const int close_mode_table[] = {
  355. DestroyAll,
  356. RetainPermanent,
  357. RetainTemporary,
  358. };
  359. #define Close_mode_val(i) (close_mode_table[Long_val(i)])
  360. CAMLprim value
  361. ml_XSetCloseDownMode( value dpy, value close_mode )
  362. {
  363. //GET_STATUS
  364. XSetCloseDownMode(
  365. Display_val(dpy),
  366. Close_mode_val(close_mode)
  367. );
  368. //CHECK_STATUS(XSetCloseDownMode,1);
  369. return Val_unit;
  370. }
  371. CAMLprim value
  372. ml_XSync( value dpy, value discard )
  373. {
  374. //GET_STATUS
  375. XSync(
  376. Display_val(dpy),
  377. Bool_val(discard)
  378. );
  379. //CHECK_STATUS(XSync,1);
  380. return Val_unit;
  381. }
  382. CAMLprim value
  383. ml_XGrabServer( value dpy )
  384. {
  385. //GET_STATUS
  386. XGrabServer(
  387. Display_val(dpy)
  388. );
  389. //CHECK_STATUS(XGrabServer,1);
  390. return Val_unit;
  391. }
  392. CAMLprim value
  393. ml_XUngrabServer( value dpy )
  394. {
  395. //GET_STATUS
  396. XUngrabServer(
  397. Display_val(dpy)
  398. );
  399. //CHECK_STATUS(XUngrabServer,1);
  400. return Val_unit;
  401. }
  402. CAMLprim value
  403. ml_XUngrabPointer( value dpy, value time )
  404. {
  405. //GET_STATUS
  406. XUngrabPointer(
  407. Display_val(dpy),
  408. Time_val(time)
  409. );
  410. //CHECK_STATUS(XUngrabPointer,1);
  411. return Val_unit;
  412. }
  413. CAMLprim value
  414. ml_XUngrabKeyboard( value dpy, value time )
  415. {
  416. //GET_STATUS
  417. XUngrabKeyboard(
  418. Display_val(dpy),
  419. Time_val(time)
  420. );
  421. //CHECK_STATUS(XUngrabKeyboard,1);
  422. return Val_unit;
  423. }
  424. CAMLprim value
  425. ml_XConnectionNumber( value dpy )
  426. {
  427. return Val_int( XConnectionNumber( Display_val(dpy) ));
  428. }
  429. CAMLprim value
  430. ml_XDefaultScreen( value dpy )
  431. {
  432. int screen_number = _xDefaultScreen( Display_val(dpy) );
  433. return Val_screenNB(screen_number);
  434. }
  435. CAMLprim value
  436. ml_XScreenCount( value dpy )
  437. {
  438. return Val_int( _xScreenCount( Display_val(dpy) ));
  439. }
  440. CAMLprim value
  441. ml_XDefaultRootWindow( value dpy )
  442. {
  443. return Val_Window( _xDefaultRootWindow( Display_val(dpy) ));
  444. }
  445. CAMLprim value
  446. ml_XDefaultVisual( value dpy, value screen_number )
  447. {
  448. Visual * vis = _xDefaultVisual(
  449. Display_val(dpy),
  450. ScreenNB_val(screen_number) );
  451. return Val_Visual(vis);
  452. }
  453. CAMLprim value ml_Visual_visualid( value visual ) {
  454. return Val_VisualID( Visual_val(visual)->visualid );
  455. }
  456. CAMLprim value ml_Visual_map_entries( value visual ) {
  457. return Val_int( Visual_val(visual)->map_entries );
  458. }
  459. CAMLprim value ml_Visual_bits_per_rgb( value visual ) {
  460. return Val_int( Visual_val(visual)->bits_per_rgb );
  461. }
  462. CAMLprim value ml_Visual_red_mask( value visual ) {
  463. return Val_long( Visual_val(visual)->red_mask );
  464. }
  465. CAMLprim value ml_Visual_green_mask( value visual ) {
  466. return Val_long( Visual_val(visual)->green_mask );
  467. }
  468. CAMLprim value ml_Visual_blue_mask( value visual ) {
  469. return Val_long( Visual_val(visual)->blue_mask );
  470. }
  471. CAMLprim value
  472. ml_XDefaultDepth( value dpy, value screen_number )
  473. {
  474. int depth = _xDefaultDepth(
  475. Display_val(dpy),
  476. ScreenNB_val(screen_number) );
  477. return Val_int(depth);
  478. }
  479. CAMLprim value
  480. ml_XListDepths( value dpy, value screen_number )
  481. {
  482. CAMLparam2(dpy, screen_number);
  483. CAMLlocal1(ml_depths);
  484. int i, count;
  485. int *depths = XListDepths(
  486. Display_val(dpy),
  487. ScreenNB_val(screen_number),
  488. &count
  489. );
  490. ml_depths = caml_alloc(count, 0);
  491. for (i=0; i<count; ++i) {
  492. Store_field( ml_depths, i, Val_int(depths[i]) );
  493. }
  494. XFree(depths);
  495. CAMLreturn(ml_depths);
  496. }
  497. CAMLprim value
  498. ml_XDisplayPlanes( value dpy, value screen_number )
  499. {
  500. int depth = _xDisplayPlanes(
  501. Display_val(dpy),
  502. ScreenNB_val(screen_number) );
  503. return Val_int(depth);
  504. }
  505. CAMLprim value
  506. ml_XDefaultColormap( value dpy, value screen_number )
  507. {
  508. Colormap colormap = _xDefaultColormap(
  509. Display_val(dpy),
  510. ScreenNB_val(screen_number) );
  511. return Val_Colormap(colormap);
  512. }
  513. CAMLprim value
  514. ml_XDisplayCells( value dpy, value screen_number )
  515. {
  516. int cells = _xDisplayCells(
  517. Display_val(dpy),
  518. ScreenNB_val(screen_number) );
  519. return Val_int(cells);
  520. }
  521. CAMLprim value
  522. ml_XBitmapUnit( value dpy )
  523. {
  524. return Val_int( _xBitmapUnit( Display_val(dpy) ));
  525. }
  526. CAMLprim value
  527. ml_XBitmapPad( value dpy )
  528. {
  529. return Val_int( _xBitmapPad( Display_val(dpy) ));
  530. }
  531. CAMLprim value
  532. ml_XProtocolVersion( value dpy )
  533. {
  534. return Val_int( _xProtocolVersion( Display_val(dpy) ));
  535. }
  536. CAMLprim value
  537. ml_XProtocolRevision( value dpy )
  538. {
  539. return Val_int( _xProtocolRevision( Display_val(dpy) ));
  540. }
  541. CAMLprim value
  542. ml_XVendorRelease( value dpy )
  543. {
  544. return Val_int( _xVendorRelease( Display_val(dpy) ));
  545. }
  546. CAMLprim value
  547. ml_XServerVendor( value dpy )
  548. {
  549. char * vendor = _xServerVendor( Display_val(dpy) );
  550. return caml_copy_string(vendor);
  551. }
  552. CAMLprim value
  553. ml_XBlackPixel( value dpy, value screen_number )
  554. {
  555. unsigned long color = _xBlackPixel(
  556. Display_val(dpy),
  557. ScreenNB_val(screen_number) );
  558. return Val_pixel_color(color);
  559. }
  560. CAMLprim value
  561. ml_XWhitePixel( value dpy, value screen_number )
  562. {
  563. unsigned long color = _xWhitePixel(
  564. Display_val(dpy),
  565. ScreenNB_val(screen_number) );
  566. return Val_pixel_color(color);
  567. }
  568. CAMLprim value
  569. ml_XDisplayWidth( value dpy, value screen_number )
  570. {
  571. int width = _xDisplayWidth(
  572. Display_val(dpy),
  573. ScreenNB_val(screen_number) );
  574. return Val_int(width);
  575. }
  576. CAMLprim value
  577. ml_XDisplayHeight( value dpy, value screen_number )
  578. {
  579. int height = _xDisplayHeight(
  580. Display_val(dpy),
  581. ScreenNB_val(screen_number) );
  582. return Val_int(height);
  583. }
  584. CAMLprim value
  585. ml_XRootWindow( value dpy, value screen_number )
  586. {
  587. Window win = _xRootWindow(
  588. Display_val(dpy),
  589. ScreenNB_val(screen_number) );
  590. return Val_Window(win);
  591. }
  592. CAMLprim value
  593. ml_XDefaultGC( value dpy, value screen_number )
  594. {
  595. GC gc = _xDefaultGC(
  596. Display_val(dpy),
  597. ScreenNB_val(screen_number) );
  598. return Val_GC(gc,dpy);
  599. }
  600. /* {{{ XColor */
  601. CAMLprim value
  602. ml_alloc_XColor( value unit )
  603. {
  604. CAMLparam0();
  605. CAMLlocal1(x_color);
  606. alloc_XColor(x_color);
  607. memset(XColor_val(x_color), 0, sizeof(XColor));
  608. CAMLreturn(x_color);
  609. }
  610. CAMLprim value
  611. ml_XAllocNamedColor( value dpy, value colormap, value color_name )
  612. {
  613. CAMLparam3(dpy, colormap, color_name);
  614. CAMLlocal3(xcolor_pair, screen_def, exact_def);
  615. alloc_XColor(screen_def);
  616. alloc_XColor(exact_def);
  617. //GET_STATUS
  618. XAllocNamedColor(
  619. Display_val(dpy),
  620. Colormap_val(colormap),
  621. String_val(color_name),
  622. XColor_val(screen_def),
  623. XColor_val(exact_def)
  624. );
  625. //CHECK_STATUS(XAllocNamedColor,1);
  626. xcolor_pair = caml_alloc(2, 0);
  627. Store_field( xcolor_pair, 0, screen_def );
  628. Store_field( xcolor_pair, 1, exact_def );
  629. CAMLreturn(xcolor_pair);
  630. }
  631. CAMLprim value
  632. ml_XColor_set_red( value x_color, value v )
  633. {
  634. XColor * xcolor = XColor_val(x_color);
  635. xcolor->red = Long_val(v);
  636. return Val_unit;
  637. }
  638. CAMLprim value
  639. ml_XColor_set_green( value x_color, value v )
  640. {
  641. XColor * xcolor = XColor_val(x_color);
  642. xcolor->green = Long_val(v);
  643. return Val_unit;
  644. }
  645. CAMLprim value
  646. ml_XColor_set_blue( value x_color, value v )
  647. {
  648. XColor * xcolor = XColor_val(x_color);
  649. xcolor->blue = Long_val(v);
  650. return Val_unit;
  651. }
  652. CAMLprim value
  653. ml_XColor_set_rgb( value x_color, value r, value g, value b )
  654. {
  655. XColor * xcolor = XColor_val(x_color);
  656. xcolor->red = Long_val(r);
  657. xcolor->green = Long_val(g);
  658. xcolor->blue = Long_val(b);
  659. return Val_unit;
  660. }
  661. static const char color_flags_table[] = {
  662. DoRed,
  663. DoGreen,
  664. DoBlue,
  665. };
  666. CAMLprim value
  667. ml_XColor_set_flags( value x_color, value mask_list )
  668. {
  669. XColor * xcolor = XColor_val(x_color);
  670. while ( mask_list != Val_emptylist )
  671. {
  672. value head = Field(mask_list, 0);
  673. xcolor->flags |= color_flags_table[Long_val(head)];
  674. mask_list = Field(mask_list, 1);
  675. }
  676. return Val_unit;
  677. }
  678. CAMLprim value
  679. ml_XAllocColor( value dpy, value colormap, value x_color )
  680. {
  681. XColor * xcolor = XColor_val(x_color);
  682. XAllocColor( Display_val(dpy), Colormap_val(colormap), xcolor );
  683. return Val_unit;
  684. }
  685. CAMLprim value
  686. ml_XAllocColorCells(
  687. value dpy,
  688. value colormap,
  689. value contig,
  690. value nplanes,
  691. value npixels )
  692. {
  693. CAMLparam5(dpy, colormap, contig, nplanes, npixels);
  694. CAMLlocal3(ret, pixels_arr, plnmsk_arr);
  695. unsigned long *pixels = NULL;
  696. unsigned long *plane_masks = NULL;
  697. long i;
  698. pixels = malloc(UInt_val(npixels) * sizeof(unsigned long));
  699. if (pixels == NULL) {
  700. caml_failwith("xAllocColorCells: out of memory");
  701. }
  702. plane_masks = malloc(UInt_val(nplanes) * sizeof(unsigned long));
  703. if (plane_masks == NULL) {
  704. free(pixels);
  705. caml_failwith("xAllocColorCells: out of memory");
  706. }
  707. Status status = XAllocColorCells(
  708. Display_val(dpy),
  709. Colormap_val(colormap),
  710. Bool_val(contig),
  711. plane_masks,
  712. UInt_val(nplanes),
  713. pixels,
  714. UInt_val(npixels)
  715. );
  716. if (!status) {
  717. free(pixels);
  718. free(plane_masks);
  719. caml_failwith("xAllocColorCells: "
  720. "can't alloc enough colors in the current color map");
  721. }
  722. pixels_arr = caml_alloc(UInt_val(npixels), 0);
  723. for (i=0; i < UInt_val(npixels); ++i)
  724. {
  725. Store_field( pixels_arr, i, Val_ulong(pixels[i]) );
  726. }
  727. free(pixels);
  728. plnmsk_arr = caml_alloc(UInt_val(nplanes), 0);
  729. for (i=0; i < UInt_val(nplanes); ++i)
  730. {
  731. Store_field( plnmsk_arr, i, Val_ulong(plane_masks[i]) );
  732. }
  733. free(plane_masks);
  734. ret = caml_alloc(2, 0);
  735. Store_field(ret, 0, pixels_arr );
  736. Store_field(ret, 1, plnmsk_arr );
  737. CAMLreturn(ret);
  738. }
  739. CAMLprim value
  740. ml_XAllocColorCellsPixels(
  741. value dpy,
  742. value colormap,
  743. value contig,
  744. value npixels )
  745. {
  746. CAMLparam4(dpy, colormap, contig, npixels);
  747. CAMLlocal1(pixels_arr);
  748. unsigned long *pixels = NULL;
  749. long i;
  750. pixels = malloc(UInt_val(npixels) * sizeof(unsigned long));
  751. if (pixels == NULL) caml_failwith("xAllocColorCells: out of memory");
  752. Status status = XAllocColorCells(
  753. Display_val(dpy),
  754. Colormap_val(colormap),
  755. Bool_val(contig),
  756. NULL, 0,
  757. pixels,
  758. UInt_val(npixels)
  759. );
  760. if (!status) {
  761. free(pixels);
  762. caml_failwith("xAllocColorCells: "
  763. "can't alloc enough colors in the current color map");
  764. }
  765. pixels_arr = caml_alloc(UInt_val(npixels), 0);
  766. for (i=0; i < UInt_val(npixels); ++i)
  767. {
  768. Store_field( pixels_arr, i, Val_ulong(pixels[i]) );
  769. }
  770. free(pixels);
  771. CAMLreturn(pixels_arr);
  772. }
  773. CAMLprim value
  774. ml_XColor_pixel( value x_color )
  775. {
  776. XColor * xcolor = XColor_val(x_color);
  777. return Val_pixel_color(xcolor->pixel);
  778. }
  779. CAMLprim value
  780. ml_XColor_set_pixel( value x_color, value pixel_color )
  781. {
  782. XColor * xcolor = XColor_val(x_color);
  783. xcolor->pixel = Pixel_color_val(pixel_color);
  784. return Val_unit;
  785. }
  786. CAMLprim value
  787. ml_XQueryColor( value dpy, value colormap, value x_color )
  788. {
  789. XQueryColor(
  790. Display_val(dpy),
  791. Colormap_val(colormap),
  792. XColor_val(x_color)
  793. );
  794. return Val_unit;
  795. }
  796. CAMLprim value
  797. ml_XColor_get_red( value x_color )
  798. {
  799. XColor * xcolor = XColor_val(x_color);
  800. return Val_long(xcolor->red);
  801. }
  802. CAMLprim value
  803. ml_XColor_get_green( value x_color )
  804. {
  805. XColor * xcolor = XColor_val(x_color);
  806. return Val_long(xcolor->green);
  807. }
  808. CAMLprim value
  809. ml_XColor_get_blue( value x_color )
  810. {
  811. XColor * xcolor = XColor_val(x_color);
  812. return Val_long(xcolor->blue);
  813. }
  814. CAMLprim value
  815. ml_XColor_get_rgb( value x_color )
  816. {
  817. CAMLparam1(x_color);
  818. CAMLlocal1(rgb);
  819. XColor * xcolor = XColor_val(x_color);
  820. rgb = caml_alloc(3, 0);
  821. Store_field( rgb, 0, Val_long(xcolor->red) );
  822. Store_field( rgb, 1, Val_long(xcolor->green) );
  823. Store_field( rgb, 2, Val_long(xcolor->blue) );
  824. CAMLreturn(rgb);
  825. }
  826. /* }}} */
  827. CAMLprim value
  828. ml_XCreateSimpleWindow( value dpy, value parent, value x, value y,
  829. value width, value height, value border_width,
  830. value border, value background)
  831. {
  832. Window win = XCreateSimpleWindow(
  833. Display_val(dpy),
  834. Window_val(parent),
  835. Int_val(x),
  836. Int_val(y),
  837. UInt_val(width),
  838. UInt_val(height),
  839. UInt_val(border_width),
  840. Pixel_color_val(border),
  841. Pixel_color_val(background) );
  842. return Val_Window(win);
  843. }
  844. CAMLprim value
  845. ml_XCreateSimpleWindow_bytecode( value * argv, int argn )
  846. {
  847. return ml_XCreateSimpleWindow( argv[0], argv[1], argv[2], argv[3],
  848. argv[4], argv[5], argv[6], argv[7], argv[8] );
  849. }
  850. CAMLprim value
  851. ml_XDestroyWindow( value dpy, value win )
  852. {
  853. GET_STATUS XDestroyWindow(
  854. Display_val(dpy),
  855. Window_val(win) );
  856. CHECK_STATUS(XDestroyWindow, 1);
  857. return Val_unit;
  858. }
  859. CAMLprim value
  860. caml_get_xid(value xid)
  861. {
  862. return Val_XID(Long_val(xid));
  863. }
  864. CAMLprim value
  865. ml_alloc_XVisualInfo( value unit )
  866. {
  867. CAMLparam0();
  868. CAMLlocal1(visInfo);
  869. alloc_XVisualInfo(visInfo);
  870. memset(XVisualInfo_val(visInfo), 0, sizeof(XVisualInfo));
  871. CAMLreturn(visInfo);
  872. }
  873. static const long vinfo_mask_table[] = {
  874. VisualNoMask,
  875. VisualIDMask,
  876. VisualScreenMask,
  877. VisualDepthMask,
  878. VisualClassMask,
  879. VisualRedMaskMask,
  880. VisualGreenMaskMask,
  881. VisualBlueMaskMask,
  882. VisualColormapSizeMask,
  883. VisualBitsPerRGBMask,
  884. VisualAllMask,
  885. };
  886. static inline long
  887. vinfo_mask_val( value mask_list )
  888. {
  889. long c_mask = 0;
  890. while ( mask_list != Val_emptylist )
  891. {
  892. value head = Field(mask_list, 0);
  893. c_mask |= vinfo_mask_table[Long_val(head)];
  894. mask_list = Field(mask_list, 1);
  895. }
  896. return c_mask;
  897. }
  898. CAMLprim value
  899. ml_XGetVisualInfo( value dpy, value vinfo_mask, value vinfo_template )
  900. {
  901. CAMLparam3(dpy, vinfo_mask, vinfo_template);
  902. CAMLlocal2(via, visual_info);
  903. int i, nitems;
  904. XVisualInfo *visInfo = XGetVisualInfo(
  905. Display_val(dpy),
  906. vinfo_mask_val(vinfo_mask),
  907. XVisualInfo_val(vinfo_template),
  908. &nitems
  909. );
  910. if (!visInfo) caml_failwith("xGetVisualInfo: can't get visual");
  911. via = caml_alloc(nitems, 0);
  912. for (i=0; i<nitems; i++) {
  913. alloc_XVisualInfo(visual_info);
  914. memcpy(XVisualInfo_val(visual_info), &(visInfo[i]), sizeof(XVisualInfo));
  915. //XFree(visInfo[i]);
  916. Store_field(via, i, visual_info);
  917. }
  918. XFree(visInfo);
  919. CAMLreturn(via);
  920. }
  921. static const int color_class_table[] = {
  922. StaticGray,
  923. GrayScale,
  924. StaticColor,
  925. PseudoColor,
  926. TrueColor,
  927. DirectColor,
  928. };
  929. #define Color_class_val(v) (color_class_table[Long_val(v)])
  930. #define XVisualInfo_set_field(Conv_val, field) \
  931. CAMLprim value ml_XVisualInfo_set_##field( value visinfo, value v ) { \
  932. XVisualInfo *vi = XVisualInfo_val(visinfo); \
  933. vi->field = Conv_val(v); \
  934. return Val_unit; \
  935. }
  936. XVisualInfo_set_field( Visual_val, visual )
  937. XVisualInfo_set_field( VisualID_val, visualid )
  938. XVisualInfo_set_field( ScreenNB_val, screen )
  939. XVisualInfo_set_field( Long_val, depth )
  940. XVisualInfo_set_field( Color_class_val, class )
  941. XVisualInfo_set_field( ULong_val, red_mask )
  942. XVisualInfo_set_field( ULong_val, green_mask )
  943. XVisualInfo_set_field( ULong_val, blue_mask )
  944. XVisualInfo_set_field( Long_val, colormap_size )
  945. XVisualInfo_set_field( Long_val, bits_per_rgb )
  946. CAMLprim value
  947. ml_XMatchVisualInfo( value dpy, value screen, value depth, value color_class )
  948. {
  949. CAMLparam4(dpy, screen, depth, color_class);
  950. CAMLlocal1(visual_info);
  951. alloc_XVisualInfo(visual_info);
  952. Status st = XMatchVisualInfo(
  953. Display_val(dpy),
  954. ScreenNB_val(screen),
  955. Int_val(depth),
  956. Color_class_val(color_class),
  957. XVisualInfo_val(visual_info)
  958. );
  959. if (st == False) caml_failwith("xMatchVisualInfo: no visual found");
  960. CAMLreturn(visual_info);
  961. }
  962. CAMLprim value
  963. ml_XVisualInfo_contents( value visual_info )
  964. {
  965. CAMLparam1(visual_info);
  966. CAMLlocal1(dat);
  967. XVisualInfo * vi = XVisualInfo_val(visual_info);
  968. dat = caml_alloc(9, 0);
  969. Store_field( dat, 0, Val_Visual(vi->visual) );
  970. Store_field( dat, 1, Val_VisualID(vi->visualid) );
  971. Store_field( dat, 2, Val_screenNB(vi->screen) );
  972. Store_field( dat, 3, Val_int(vi->depth) );
  973. Store_field( dat, 4, Val_long(vi->red_mask) );
  974. Store_field( dat, 5, Val_long(vi->green_mask) );
  975. Store_field( dat, 6, Val_long(vi->blue_mask) );
  976. Store_field( dat, 7, Val_int(vi->colormap_size) );
  977. Store_field( dat, 8, Val_int(vi->bits_per_rgb) );
  978. CAMLreturn(dat);
  979. }
  980. CAMLprim value
  981. ml_XFree_XVisualInfo( value visual_info )
  982. {
  983. XVisualInfo * vi = XVisualInfo_val(visual_info);
  984. if (vi == NULL) {
  985. caml_invalid_argument("xFree_xVisualInfo: xVisualInfo NULL pointer");
  986. } else {
  987. XFree( vi );
  988. vi = NULL;
  989. }
  990. return Val_unit;
  991. }
  992. CAMLprim value
  993. ml_XCreateColormap( value dpy, value win, value visual, value alloc )
  994. {
  995. Colormap colormap = XCreateColormap(
  996. Display_val(dpy),
  997. Window_val(win),
  998. Visual_val(visual),
  999. ( Int_val(alloc) ? AllocAll : AllocNone)
  1000. );
  1001. return Val_Colormap(colormap);
  1002. }
  1003. CAMLprim value
  1004. ml_XFreeColormap( value dpy, value colormap )
  1005. {
  1006. GET_STATUS XFreeColormap(
  1007. Display_val(dpy),
  1008. Colormap_val(colormap) );
  1009. CHECK_STATUS(XFreeColormap,1);
  1010. return Val_unit;
  1011. }
  1012. CAMLprim value
  1013. ml_XCopyColormapAndFree( value dpy, value colormap )
  1014. {
  1015. Colormap new_colormap = XCopyColormapAndFree(
  1016. Display_val(dpy),
  1017. Colormap_val(colormap) );
  1018. /*
  1019. if ((new_colormap=XCopyColormapAndFree(Display_val(dpy),
  1020. Colormap_val(colormap))) == BadAlloc)
  1021. caml_failwith("Can't Create new colormap");
  1022. */
  1023. return Val_Colormap(new_colormap);
  1024. }
  1025. CAMLprim value
  1026. ml_XSetWindowColormap( value dpy, value win, value colormap )
  1027. {
  1028. GET_STATUS XSetWindowColormap(
  1029. Display_val(dpy),
  1030. Window_val(win),
  1031. Colormap_val(colormap) );
  1032. CHECK_STATUS(XSetWindowColormap,1);
  1033. return Val_unit;
  1034. }
  1035. CAMLprim value
  1036. _ml_XSetWindowAttributes_alloc( value unit )
  1037. {
  1038. CAMLparam0();
  1039. CAMLlocal2(ret, wattr);
  1040. alloc_XSetWindowAttributes(wattr);
  1041. ret = caml_alloc(2, 0);
  1042. Store_field(ret, 0, wattr );
  1043. Store_field(ret, 1, (value) 0 );
  1044. CAMLreturn(ret);
  1045. }
  1046. CAMLprim value
  1047. ml_XSetWindowAttributes_alloc( value unit )
  1048. {
  1049. CAMLparam0();
  1050. CAMLlocal1(wattr);
  1051. alloc_XSetWindowAttributes(wattr);
  1052. CAMLreturn(wattr);
  1053. }
  1054. #define WATTR_SET(field_c_type, attr_field, field_mask, Conv_val, ml_type) \
  1055. \
  1056. CAMLprim value \
  1057. ml_xSetWindowAttributes_set_##attr_field( value ml_wattr, value _##attr_field ) \
  1058. { \
  1059. XSetWindowAttributes * wattr; \
  1060. wattr = XSetWindowAttributes_val(ml_wattr); \
  1061. wattr->attr_field = Conv_val(_##attr_field); \
  1062. return Val_unit; \
  1063. }
  1064. /* setting the fields of the struct XSetWindowAttributes and the associated mask */
  1065. WATTR_SET( Pixmap, background_pixmap, CWBackPixmap, Pixmap_val, pixmap )
  1066. WATTR_SET( unsigned long, background_pixel, CWBackPixel, Pixel_color_val, uint )
  1067. WATTR_SET( Pixmap, border_pixmap, CWBorderPixmap, Pixmap_val, pixmap )
  1068. WATTR_SET( unsigned long, border_pixel, CWBorderPixel, Pixel_color_val, uint )
  1069. WATTR_SET( int, bit_gravity, CWBitGravity, Int_val, int )
  1070. WATTR_SET( int, win_gravity, CWWinGravity, Int_val, int )
  1071. WATTR_SET( int, backing_store, CWBackingStore, Int_val, int )
  1072. WATTR_SET( unsigned long, backing_planes, CWBackingPlanes, ULong_val, uint )//XXX
  1073. WATTR_SET( unsigned long, backing_pixel, CWBackingPixel, ULong_val, uint )//pixel_color?
  1074. WATTR_SET( Bool, save_under, CWSaveUnder, Bool_val, bool )
  1075. WATTR_SET( long, event_mask, CWEventMask, Eventmask_val, event_mask_list )
  1076. WATTR_SET( long, do_not_propagate_mask, CWDontPropagate, Long_val, int )
  1077. WATTR_SET( Bool, override_redirect, CWOverrideRedirect, Bool_val, bool )
  1078. WATTR_SET( Colormap, colormap, CWColormap, Colormap_val, colormap )
  1079. WATTR_SET( Cursor, cursor, CWCursor, Cursor_val, cursor )
  1080. static const unsigned int window_class_table[] = {
  1081. CopyFromParent,
  1082. InputOutput,
  1083. InputOnly,
  1084. };
  1085. static const unsigned long winattr_valuemask_table[] = {
  1086. CWBackPixmap,
  1087. CWBackPixel,
  1088. CWBorderPixmap,
  1089. CWBorderPixel,
  1090. CWBitGravity,
  1091. CWWinGravity,
  1092. CWBackingStore,
  1093. CWBackingPlanes,
  1094. CWBackingPixel,
  1095. CWOverrideRedirect,
  1096. CWSaveUnder,
  1097. CWEventMask,
  1098. CWDontPropagate,
  1099. CWColormap,
  1100. CWCursor,
  1101. };
  1102. static inline unsigned long
  1103. winattr_valuemask_val( value mask_list )
  1104. {
  1105. unsigned long c_mask = 0;
  1106. while ( mask_list != Val_emptylist )
  1107. {
  1108. value head = Field(mask_list, 0);
  1109. c_mask |= winattr_valuemask_table[Long_val(head)];
  1110. mask_list = Field(mask_list, 1);
  1111. }
  1112. return c_mask;
  1113. }
  1114. CAMLprim value
  1115. ml_XGetWindowAttributes( value dpy, value win )
  1116. {
  1117. CAMLparam2(dpy, win);
  1118. CAMLlocal1(wattr);
  1119. alloc_XWindowAttributes(wattr);
  1120. //GET_STATUS
  1121. XGetWindowAttributes(
  1122. Display_val(dpy),
  1123. Window_val(win),
  1124. XWindowAttributes_val(wattr)
  1125. );
  1126. //CHECK_STATUS(XGetWindowAttributes,1);
  1127. CAMLreturn(wattr);
  1128. }
  1129. #define quote(s) #s
  1130. #define WATTR_GET( Val_conv, field_name, ml_type ) \
  1131. \
  1132. CAMLprim value \
  1133. ml_XWindowAttributes_##field_name( value wattr ) { \
  1134. return Val_conv( XWindowAttributes_val(wattr)->field_name ); \
  1135. }
  1136. #define WATTR_GML( Val_conv, field_name, ml_type ) \
  1137. external xWindowAttributes_##field_name: xWindowAttributes -> ml_type = quote(ml_XWindowAttributes_##field_name)
  1138. WATTR_GET( Val_int, x, int )
  1139. WATTR_GET( Val_int, y, int )
  1140. WATTR_GET( Val_int, width, int )
  1141. WATTR_GET( Val_int, height, int )
  1142. WATTR_GET( Val_int, depth, int )
  1143. WATTR_GET( Val_XScreen, screen, xScreen )
  1144. WATTR_GET( Val_int, border_width, int )
  1145. WATTR_GET( Val_Colormap, colormap, colormap )
  1146. WATTR_GET( Val_bool, map_installed, bool )
  1147. CAMLprim value
  1148. ml_XWindowAttributes_all( value dpy, value win )
  1149. {
  1150. CAMLparam2(dpy, win);
  1151. CAMLlocal1(wattrs);
  1152. XWindowAttributes c_wattr;
  1153. //GET_STATUS
  1154. XGetWindowAttributes(
  1155. Display_val(dpy),
  1156. Window_val(win),
  1157. &c_wattr
  1158. );
  1159. //CHECK_STATUS(XGetWindowAttributes,1);
  1160. wattrs = caml_alloc(5, 0);
  1161. Store_field( wattrs, 0, Val_int( c_wattr.x ) );
  1162. Store_field( wattrs, 1, Val_int( c_wattr.y ) );
  1163. Store_field( wattrs, 2, Val_int( c_wattr.width ) );
  1164. Store_field( wattrs, 3, Val_int( c_wattr.height ) );
  1165. Store_field( wattrs, 4, Val_int( c_wattr.depth ) );
  1166. CAMLreturn(wattrs);
  1167. }
  1168. #if 0
  1169. typedef struct {
  1170. int x, y; /* location of window */
  1171. int width, height; /* width and height of window */
  1172. int border_width; /* border width of window */
  1173. int depth; /* depth of window */
  1174. Visual *visual; /* the associated visual structure */
  1175. Window root; /* root of screen containing window */
  1176. #if defined(__cplusplus) || defined(c_plusplus)
  1177. int c_class; /* C++ InputOutput, InputOnly*/
  1178. #else
  1179. int class; /* InputOutput, InputOnly*/
  1180. #endif
  1181. int bit_gravity; /* one of bit gravity values */
  1182. int win_gravity; /* one of the window gravity values */
  1183. int backing_store; /* NotUseful, WhenMapped, Always */
  1184. unsigned long backing_planes;/* planes to be preserved if possible */
  1185. unsigned long backing_pixel;/* value to be used when restoring planes */
  1186. Bool save_under; /* boolean, should bits under be saved? */
  1187. Colormap colormap; /* color map to be associated with window */
  1188. Bool map_installed; /* boolean, is color map currently installed*/
  1189. int map_state; /* IsUnmapped, IsUnviewable, IsViewable */
  1190. long all_event_masks; /* set of events all people have interest in*/
  1191. long your_event_mask; /* my event mask */
  1192. long do_not_propagate_mask; /* set of events that should not propagate */
  1193. Bool override_redirect; /* boolean value for override-redirect */
  1194. Screen *screen; /* back pointer to correct screen */
  1195. } XWindowAttributes;
  1196. #endif
  1197. CAMLprim value
  1198. ml_XCreateWindow(
  1199. value dpy, value parent,
  1200. value x, value y,
  1201. value width, value height,
  1202. value border_width,
  1203. value depth, value class, value visual,
  1204. value valuemask, value attributes )
  1205. {
  1206. Window win = XCreateWindow(
  1207. Display_val(dpy),
  1208. Window_val(parent),
  1209. Int_val(x),
  1210. Int_val(y),
  1211. UInt_val(width),
  1212. UInt_val(height),
  1213. UInt_val(border_width),
  1214. Int_val(depth),
  1215. window_class_table[Long_val(class)],
  1216. Visual_val(visual),
  1217. winattr_valuemask_val(valuemask),
  1218. XSetWindowAttributes_val(attributes)
  1219. );
  1220. if (!win) caml_failwith("XCreateWindow");
  1221. return Val_Window(win);
  1222. }
  1223. CAMLprim value
  1224. ml_XCreateWindow_bytecode( value * argv, int argn )
  1225. {
  1226. return ml_XCreateWindow( argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
  1227. argv[6], argv[7], argv[8], argv[9], argv[10], argv[11] );
  1228. }
  1229. CAMLprim value
  1230. ml_XResizeWindow( value dpy, value win, value width, value height )
  1231. {
  1232. GET_STATUS XResizeWindow(
  1233. Display_val(dpy),
  1234. Window_val(win),
  1235. UInt_val(width),
  1236. UInt_val(height)
  1237. );
  1238. CHECK_STATUS(XResizeWindow,1);
  1239. return Val_unit;
  1240. }
  1241. CAMLprim value
  1242. ml_XMoveWindow( value dpy, value win, value x, value y )
  1243. {
  1244. GET_STATUS XMoveWindow(
  1245. Display_val(dpy),
  1246. Window_val(win),
  1247. Int_val(x),
  1248. Int_val(y)
  1249. );
  1250. CHECK_STATUS(XMoveWindow,1);
  1251. return Val_unit;
  1252. }
  1253. CAMLprim value
  1254. ml_XMoveResizeWindow( value dpy, value win, value x, value y, value width, value height )
  1255. {
  1256. GET_STATUS XMoveResizeWindow(
  1257. Display_val(dpy),
  1258. Window_val(win),
  1259. Int_val(x),
  1260. Int_val(y),
  1261. UInt_val(width),
  1262. UInt_val(height)
  1263. );
  1264. CHECK_STATUS(XMoveResizeWindow,1);
  1265. return Val_unit;
  1266. }
  1267. CAMLprim value
  1268. ml_XMoveResizeWindow_bytecode( value * argv, int argn )
  1269. {
  1270. return ml_XMoveResizeWindow( argv[0], argv[1], argv[2],
  1271. argv[3], argv[4], argv[5] );
  1272. }
  1273. CAMLprim value
  1274. ml_XLowerWindow( value dpy, value win )
  1275. {
  1276. GET_STATUS XLowerWindow(
  1277. Display_val(dpy),
  1278. Window_val(win) );
  1279. CHECK_STATUS(XLowerWindow,1);
  1280. return Val_unit;
  1281. }
  1282. CAMLprim value
  1283. ml_XRaiseWindow( value dpy, value win )
  1284. {
  1285. GET_STATUS XRaiseWindow(
  1286. Display_val(dpy),
  1287. Window_val(win) );
  1288. CHECK_STATUS(XRaiseWindow,1);
  1289. return Val_unit;
  1290. }
  1291. CAMLprim value
  1292. ml_XStoreName( value dpy, value win, value name )
  1293. {
  1294. GET_STATUS XStoreName(
  1295. Display_val(dpy),
  1296. Window_val(win),
  1297. String_val(name) );
  1298. CHECK_STATUS(XStoreName, 1);
  1299. return Val_unit;
  1300. }
  1301. CAMLprim value
  1302. ml_XFetchName( value dpy, value win )
  1303. {
  1304. CAMLlocal1( ml_window_name );
  1305. char * window_name = NULL;
  1306. //GET_STATUS
  1307. XFetchName(
  1308. Display_val(dpy),
  1309. Window_val(win),
  1310. &window_name
  1311. );
  1312. //CHECK_STATUS(XFetchName,1);
  1313. if (window_name != NULL) {
  1314. ml_window_name = caml_copy_string(window_name);
  1315. XFree(window_name);
  1316. } else {
  1317. caml_failwith("xFetchName");
  1318. }
  1319. return ml_window_name;
  1320. }
  1321. CAMLprim value
  1322. ml_XSelectInput( value dpy, value win, value ml_event_mask )
  1323. {
  1324. long event_mask = Eventmask_val( ml_event_mask );
  1325. GET_STATUS XSelectInput(
  1326. Display_val(dpy),
  1327. Window_val(win),
  1328. event_mask );
  1329. CHECK_STATUS(XSelectInput, 1);
  1330. return Val_unit;
  1331. }
  1332. CAMLprim value
  1333. ml_XMapWindow( value dpy, value win )
  1334. {
  1335. GET_STATUS XMapWindow(
  1336. Display_val(dpy),
  1337. Window_val(win) );
  1338. CHECK_STATUS(XMapWindow, 1);
  1339. return Val_unit;
  1340. }
  1341. CAMLprim value
  1342. ml_XMapSubwindows( value dpy, value win )
  1343. {
  1344. GET_STATUS XMapSubwindows(
  1345. Display_val(dpy),
  1346. Window_val(win) );
  1347. CHECK_STATUS(XMapSubwindows, 1);
  1348. return Val_unit;
  1349. }
  1350. CAMLprim value
  1351. ml_XMapRaised( value dpy, value win )
  1352. {
  1353. //GET_STATUS
  1354. XMapRaised(
  1355. Display_val(dpy),
  1356. Window_val(win) );
  1357. //CHECK_STATUS(XMapRaised, 1);
  1358. return Val_unit;
  1359. }
  1360. CAMLprim value
  1361. ml_XUnmapWindow( value dpy, value win )
  1362. {
  1363. //GET_STATUS
  1364. XUnmapWindow(
  1365. Display_val(dpy),
  1366. Window_val(win) );
  1367. //CHECK_STATUS(XUnmapWindow,1);
  1368. return Val_unit;
  1369. }
  1370. CAMLprim value
  1371. ml_XReparentWindow( value dpy, value win, value parent, value x, value y )
  1372. {
  1373. GET_STATUS XReparentWindow(
  1374. Display_val(dpy),
  1375. Window_val(win),
  1376. Window_val(parent),
  1377. Int_val(x),
  1378. Int_val(y)
  1379. );
  1380. CHECK_STATUS(XReparentWindow,1);
  1381. return Val_unit;
  1382. }
  1383. CAMLprim value
  1384. ml_XChangeSaveSet( value dpy, value win, value change_mode )
  1385. {
  1386. //GET_STATUS
  1387. XChangeSaveSet(
  1388. Display_val(dpy),
  1389. Window_val(win),
  1390. (Int_val(change_mode) ? SetModeDelete : SetModeInsert)
  1391. );
  1392. //CHECK_STATUS(XChangeSaveSet,1);
  1393. return Val_unit;
  1394. }
  1395. CAMLprim value
  1396. ml_XAddToSaveSet( value dpy, value win )
  1397. {
  1398. //GET_STATUS
  1399. XAddToSaveSet(
  1400. Display_val(dpy),
  1401. Window_val(win)
  1402. );
  1403. //CHECK_STATUS(XAddToSaveSet,1);
  1404. return Val_unit;
  1405. }
  1406. CAMLprim value
  1407. ml_XRemoveFromSaveSet( value dpy, value win )
  1408. {
  1409. //GET_STATUS
  1410. XRemoveFromSaveSet(
  1411. Display_val(dpy),
  1412. Window_val(win)
  1413. );
  1414. //CHECK_STATUS(XRemoveFromSaveSet,1);
  1415. return Val_unit;
  1416. }
  1417. CAMLprim value
  1418. ml_XQueryTree( value dpy, value win )
  1419. {
  1420. CAMLparam2( dpy, win );
  1421. CAMLlocal2( ret, children_arr );
  1422. Window root_win, parent_win, *children;
  1423. unsigned int nchildren, i;
  1424. children = NULL;
  1425. Status status = XQueryTree(
  1426. Display_val(dpy),
  1427. Window_val(win),
  1428. &root_win,
  1429. &parent_win,
  1430. &children,
  1431. &nchildren
  1432. );
  1433. if (status != 1) {
  1434. if (children != NULL) XFree(children);
  1435. caml_failwith("xQueryTree");
  1436. }
  1437. children_arr = caml_alloc(nchildren, 0);
  1438. for (i=0; i < nchildren; i++) {
  1439. Store_field( children_arr, i, Val_Window(children[i]) );
  1440. }
  1441. XFree(children);
  1442. ret = caml_alloc(3, 0);
  1443. Store_field( ret, 0, Val_Window(root_win) );
  1444. Store_field( ret, 1, Val_Window(parent_win) );
  1445. Store_field( ret, 2, children_arr );
  1446. CAMLreturn( ret );
  1447. }
  1448. CAMLprim value
  1449. ml_XRestackWindows( value dpy, value ml_wins )
  1450. {
  1451. int nwindows, i;
  1452. Window* windows;
  1453. nwindows = Wosize_val(ml_wins);
  1454. windows = malloc(nwindows * sizeof(Window*));
  1455. for (i=0; i < nwindows; i++) {
  1456. windows[i] = Window_val(Field(ml_wins, i));
  1457. }
  1458. //GET_STATUS
  1459. XRestackWindows(
  1460. Display_val(dpy),
  1461. windows,
  1462. nwindows
  1463. );
  1464. free(windows);
  1465. //CHECK_STATUS(XRestackWindows,1);
  1466. return Val_unit;
  1467. }
  1468. static const int circulateSubwinsDir_table[] = {
  1469. RaiseLowest,
  1470. LowerHighest
  1471. };
  1472. #define CirculateSubwinsDir_val(i) (circulateSubwinsDir_table[Long_val(i)])
  1473. CAMLprim value
  1474. ml_XCirculateSubwindows( value dpy, value win, value dir )
  1475. {
  1476. //GET_STATUS
  1477. XCirculateSubwindows(
  1478. Display_val(dpy),
  1479. Window_val(win),
  1480. CirculateSubwinsDir_val(dir)
  1481. );
  1482. //CHECK_STATUS(XCirculateSubwindows,1);
  1483. return Val_unit;
  1484. }
  1485. CAMLprim value
  1486. ml_XCirculateSubwindowsDown( value dpy, value win )
  1487. {
  1488. //GET_STATUS
  1489. XCirculateSubwindowsDown(
  1490. Display_val(dpy),
  1491. Window_val(win)
  1492. );
  1493. //CHECK_STATUS(XCirculateSubwindowsDown,1);
  1494. return Val_unit;
  1495. }
  1496. CAMLprim value
  1497. ml_XCirculateSubwindowsUp( value dpy, value win )
  1498. {
  1499. //GET_STATUS
  1500. XCirculateSubwindowsUp(
  1501. Display_val(dpy),
  1502. Window_val(win)
  1503. );
  1504. //CHECK_STATUS(XCirculateSubwindowsUp,1);
  1505. return Val_unit;
  1506. }
  1507. CAMLprim value
  1508. ml_XGetWindowProperty_string(
  1509. value dpy,
  1510. value win,
  1511. value property,
  1512. value long_offset,
  1513. value long_length,
  1514. value delete,
  1515. value req_type
  1516. )
  1517. {
  1518. CAMLparam5(dpy, win, property, long_offset, long_length);
  1519. CAMLxparam2(delete, req_type);
  1520. CAMLlocal1(ret);
  1521. Atom actual_type;
  1522. int actual_format;
  1523. unsigned long nitems, bytes_after;
  1524. /*unsigned*/ char* prop;
  1525. (void) XGetWindowProperty(
  1526. Display_val(dpy),
  1527. Window_val(win),
  1528. Atom_val(property),
  1529. Long_val(long_offset),
  1530. Long_val(long_length),
  1531. Bool_val(delete),
  1532. AnyPropertyType, // Atom req_type, TODO
  1533. &actual_type,
  1534. &actual_format,
  1535. &nitems,
  1536. &bytes_after,
  1537. (unsigned char**)&prop
  1538. );
  1539. ret = caml_alloc(5, 0);
  1540. Store_field(ret, 0, Val_Atom(actual_type) );
  1541. Store_field(ret, 1, Val_int(actual_format) );
  1542. Store_field(ret, 2, Val_long(nitems) );
  1543. Store_field(ret, 3, Val_long(bytes_after) );
  1544. Store_field(ret, 4, caml_copy_string(prop) );
  1545. XFree(prop);
  1546. CAMLreturn(ret);
  1547. }
  1548. CAMLprim value
  1549. ml_XGetWindowProperty_string_bytecode( value * argv, int argn )
  1550. {
  1551. return ml_XGetWindowProperty_string( argv[0], argv[1], argv[2],
  1552. argv[3], argv[4], argv[5], argv[6] );
  1553. }
  1554. CAMLprim value
  1555. ml_XGetWindowProperty_window(
  1556. value dpy,
  1557. value win,
  1558. value property,
  1559. value long_offset,
  1560. value long_length,
  1561. value delete,
  1562. value req_type
  1563. )
  1564. {
  1565. CAMLparam5(dpy, win, property, long_offset, long_length);
  1566. CAMLxparam2(delete, req_type);
  1567. CAMLlocal1(ret);
  1568. Atom actual_type;
  1569. int actual_format;
  1570. unsigned long nitems, bytes_after;
  1571. Window *prop;
  1572. (void) XGetWindowProperty(
  1573. Display_val(dpy),
  1574. Window_val(win),
  1575. Atom_val(property),
  1576. Long_val(long_offset),
  1577. Long_val(long_length),
  1578. Bool_val(delete),
  1579. AnyPropertyType, // Atom req_type, TODO
  1580. &actual_type,
  1581. &actual_format,
  1582. &nitems,
  1583. &bytes_after,
  1584. (unsigned char**)&prop
  1585. );
  1586. ret = caml_alloc(5, 0);
  1587. Store_field(ret, 0, Val_Atom(actual_type) );
  1588. Store_field(ret, 1, Val_int(actual_format) );
  1589. Store_field(ret, 2, Val_long(nitems) );
  1590. Store_field(ret, 3, Val_long(bytes_after) );
  1591. Store_field(ret, 4, Val_Window(prop[0]) );
  1592. XFree(prop);
  1593. CAMLreturn(ret);
  1594. }
  1595. CAMLprim value
  1596. ml_XGetWindowProperty_window_bytecode( value * argv, int argn )
  1597. {
  1598. return ml_XGetWindowProperty_window( argv[0], argv[1], argv[2],
  1599. argv[3], argv[4], argv[5], argv[6] );
  1600. }
  1601. /* Managing Installed Colormaps */
  1602. CAMLprim value
  1603. ml_XInstallColormap( value dpy, value colormap )
  1604. {
  1605. //GET_STATUS
  1606. XInstallColormap(
  1607. Display_val(dpy),
  1608. Colormap_val(colormap)
  1609. );
  1610. //CHECK_STATUS(XInstallColormap,1);
  1611. return Val_unit;
  1612. }
  1613. CAMLprim value
  1614. ml_XUninstallColormap( value dpy, value colormap )
  1615. {
  1616. //GET_STATUS
  1617. XUninstallColormap(
  1618. Display_val(dpy),
  1619. Colormap_val(colormap)
  1620. );
  1621. //CHECK_STATUS(XUninstallColormap,1);
  1622. return Val_unit;
  1623. }
  1624. CAMLprim value
  1625. ml_XListInstalledColormaps( value dpy, value win )
  1626. {
  1627. CAMLparam2(dpy, win);
  1628. CAMLlocal1(ret);
  1629. int i, num;
  1630. Colormap *colormaps =
  1631. XListInstalledColormaps(
  1632. Display_val(dpy),
  1633. Window_val(win),
  1634. &num
  1635. );
  1636. ret = caml_alloc(num, 0);
  1637. for (i=0; i<num; ++i) {
  1638. Store_field(ret, i, Val_Colormap(colormaps[i]) );
  1639. }
  1640. XFree(colormaps);
  1641. CAMLreturn(ret);
  1642. }
  1643. CAMLprim value
  1644. ml_XKillClient( value dpy, value resource )
  1645. {
  1646. //GET_STATUS
  1647. XKillClient(
  1648. Display_val(dpy),
  1649. (XID) resource
  1650. );
  1651. //CHECK_STATUS(XKillClient,1);
  1652. return Val_unit;
  1653. }
  1654. /* Threads */
  1655. CAMLprim value
  1656. ml_XInitThreads( value unit )
  1657. {
  1658. GET_STATUS XInitThreads();
  1659. CHECK_STATUS(XInitThreads,1);
  1660. return Val_unit;
  1661. }
  1662. CAMLprim value
  1663. ml_XLockDisplay( value dpy )
  1664. {
  1665. XLockDisplay( Display_val(dpy) );
  1666. return Val_unit;
  1667. }
  1668. CAMLprim value
  1669. ml_XUnlockDisplay( value dpy )
  1670. {
  1671. XUnlockDisplay( Display_val(dpy) );
  1672. return Val_unit;
  1673. }
  1674. CAMLprim value
  1675. ml_XSetWMProtocols( value dpy, value win, value protocols, value count )
  1676. {
  1677. Status status = XSetWMProtocols(
  1678. Display_val(dpy),
  1679. Window_val(win),
  1680. Atom_val_addr(protocols),
  1681. Int_val(count) );
  1682. CHECK_STATUS(XSetWMProtocols, 1);
  1683. return Val_unit;
  1684. }
  1685. CAMLprim value
  1686. ml_XInternAtom( value dpy, value atom_name, value only_if_exists )
  1687. {
  1688. Atom a = XInternAtom(
  1689. Display_val(dpy),
  1690. String_val(atom_name),
  1691. Bool_val(only_if_exists) );
  1692. if (a == None)
  1693. caml_raise_not_found();
  1694. // XInternAtom() can generate BadAlloc and BadValue errors.
  1695. return Val_Atom(a);
  1696. }
  1697. CAMLprim value
  1698. ml_XInternAtoms( value dpy, value ml_names, value only_if_exists )
  1699. {
  1700. CAMLparam3(dpy, ml_names, only_if_exists);
  1701. CAMLlocal1(ret);
  1702. int count, i;
  1703. char** names;
  1704. Atom* atoms_return;
  1705. count = Wosize_val(ml_names);
  1706. atoms_return = malloc(count * sizeof(Atom));
  1707. names = malloc(count * sizeof(char *));
  1708. for (i=0; i<count; ++i) {
  1709. names[i] = String_val(Field(ml_names,i));
  1710. }
  1711. Status st = XInternAtoms(
  1712. Display_val(dpy),
  1713. names,
  1714. count,
  1715. Bool_val(only_if_exists),
  1716. atoms_return
  1717. );
  1718. if (st == 0)
  1719. caml_failwith("xInternAtoms: atoms were not returned for all of the names");
  1720. ret = caml_alloc(count, 0);
  1721. for (i=0; i<count; ++i) {
  1722. Store_field( ret, i, Val_Atom(atoms_return[i]) );
  1723. }
  1724. free(atoms_return);
  1725. free(names);
  1726. CAMLreturn(ret);
  1727. }
  1728. CAMLprim value
  1729. ml_XGetAtomName( value dpy, value atom )
  1730. {
  1731. CAMLparam2(dpy, atom);
  1732. CAMLlocal1(ml_atom_name);
  1733. char * atom_name = XGetAtomName(
  1734. Display_val(dpy),
  1735. Atom_val(atom)
  1736. );
  1737. if (atom_name == NULL)
  1738. caml_failwith("xGetAtomName");
  1739. ml_atom_name = caml_copy_string(atom_name);
  1740. XFree((void *)atom_name);
  1741. CAMLreturn(ml_atom_name);
  1742. }
  1743. /* XSizeHints, from <X11/Xutil.h> */
  1744. CAMLprim value
  1745. ml_alloc_XSizeHints( value unit )
  1746. {
  1747. CAMLparam0();
  1748. CAMLlocal1(size_hints);
  1749. alloc_XSizeHints(size_hints);
  1750. memset(XSizeHints_val(size_hints), 0, sizeof(XSizeHints));
  1751. CAMLreturn(size_hints);
  1752. }
  1753. CAMLprim value
  1754. ml_XSizeHints_set_USPosition( value size_hints, value _x, value _y )
  1755. {
  1756. XSizeHints *sh;
  1757. sh = XSizeHints_val(size_hints);
  1758. sh->flags |= USPosition;
  1759. sh->x = Int_val(_x);
  1760. sh->y = Int_val(_y);
  1761. return Val_unit;
  1762. }
  1763. CAMLprim value
  1764. ml_XSizeHints_set_PPosition( value size_hints, value _x, value _y )
  1765. {
  1766. XSizeHints *sh;
  1767. sh = XSizeHints_val(size_hints);
  1768. sh->flags |= PPosition;
  1769. sh->x = Int_val(_x);
  1770. sh->y = Int_val(_y);
  1771. return Val_unit;
  1772. }
  1773. CAMLprim value
  1774. ml_XSizeHints_set_USSize( value size_hints, value _width, value _height )
  1775. {
  1776. XSizeHints *sh;
  1777. sh = XSizeHints_val(size_hints);
  1778. sh->flags |= USSize;
  1779. sh->width = Int_val(_width);
  1780. sh->height = Int_val(_height);
  1781. return Val_unit;
  1782. }
  1783. CAMLprim value
  1784. ml_XSizeHints_set_PSize( value size_hints, value _width, value _height )
  1785. {
  1786. XSizeHints *sh;
  1787. sh = XSizeHints_val(size_hints);
  1788. sh->flags |= PSize;
  1789. sh->width = Int_val(_width);
  1790. sh->height = Int_val(_height);
  1791. return Val_unit;
  1792. }
  1793. CAMLprim value
  1794. ml_XSizeHints_set_PMinSize( value size_hints, value _min_width, value _min_height )
  1795. {
  1796. XSizeHints *sh;
  1797. sh = XSizeHints_val(size_hints);
  1798. sh->flags |= PMinSize;
  1799. sh->min_width = Int_val(_min_width);
  1800. sh->min_height = Int_val(_min_height);
  1801. return Val_unit;
  1802. }
  1803. CAMLprim value
  1804. ml_XSizeHints_set_PMaxSize( value size_hints, value _max_width, value _max_height )
  1805. {
  1806. XSizeHints *sh;
  1807. sh = XSizeHints_val(size_hints);
  1808. sh->flags |= PMaxSize;
  1809. sh->max_width = Int_val(_max_width);
  1810. sh->max_height = Int_val(_max_height);
  1811. return Val_unit;
  1812. }
  1813. CAMLprim value
  1814. ml_XSizeHints_set_PResizeInc( value size_hints, value _width_inc, value _height_inc )
  1815. {
  1816. XSizeHints *sh;
  1817. sh = XSizeHints_val(size_hints);
  1818. sh->flags |= PResizeInc;
  1819. sh->width_inc = Int_val(_width_inc);
  1820. sh->height_inc = Int_val(_height_inc);
  1821. return Val_unit;
  1822. }
  1823. CAMLprim value
  1824. ml_XSizeHints_set_PBaseSize( value size_hints, value _base_width, value _base_height )
  1825. {
  1826. XSizeHints *sh;
  1827. sh = XSizeHints_val(size_hints);
  1828. sh->flags |= PBaseSize;
  1829. sh->base_width = Int_val(_base_width);
  1830. sh->base_height = Int_val(_base_height);
  1831. return Val_unit;
  1832. }
  1833. CAMLprim value
  1834. ml_XSizeHints_set_PAspect( value size_hints, value min_aspect, value max_aspect )
  1835. {
  1836. XSizeHints *sh;
  1837. sh = XSizeHints_val(size_hints);
  1838. sh->flags |= PAspect;
  1839. sh->min_aspect.x = Int_val(Field(min_aspect,0));
  1840. sh->min_aspect.y = Int_val(Field(min_aspect,1));
  1841. sh->max_aspect.x = Int_val(Field(max_aspect,0));
  1842. sh->max_aspect.y = Int_val(Field(max_aspect,1));
  1843. return Val_unit;
  1844. }
  1845. CAMLprim value
  1846. ml_XSizeHints_set_PWinGravity( value size_hints, value _win_gravity )
  1847. {
  1848. XSizeHints *sh;
  1849. sh = XSizeHints_val(size_hints);
  1850. sh->flags |= PWinGravity;
  1851. sh->win_gravity = Int_val(_win_gravity);
  1852. return Val_unit;
  1853. }
  1854. CAMLprim value
  1855. ml_XSetNormalHints( value dpy, value win, value size_hints )
  1856. {
  1857. XSizeHints* hints;
  1858. hints = XSizeHints_val(size_hints);
  1859. GET_STATUS XSetNormalHints(
  1860. Display_val(dpy),
  1861. Window_val(win),
  1862. hints );
  1863. CHECK_STATUS(XSetNormalHints,1);
  1864. return Val_unit;
  1865. }
  1866. CAMLprim value
  1867. ml_XSetStandardProperties(
  1868. value dpy, value win,
  1869. value window_name,
  1870. value icon_name,
  1871. value ml_icon_pixmap,
  1872. value ml_argv,
  1873. value hints )
  1874. {
  1875. int argc = Wosize_val(ml_argv);
  1876. char ** argv = malloc((argc+1) * sizeof(char*));
  1877. int i;
  1878. for (i=0; i<argc; i++) {
  1879. value ml_arg = Field(ml_argv,i);
  1880. int len = caml_string_length(ml_arg);
  1881. char *arg = String_val(ml_arg);
  1882. argv[i] = malloc((len+1) * sizeof(char));
  1883. strncpy(argv[i], arg, len);
  1884. argv[i][len] = '\0';
  1885. }
  1886. argv[argc] = NULL;
  1887. Pixmap icon_pixmap;
  1888. if (ml_icon_pixmap == Val_int(0)) icon_pixmap = None; // None
  1889. else icon_pixmap = Pixmap_val( Field(ml_icon_pixmap,0) ); // Some v
  1890. GET_STATUS XSetStandardProperties(
  1891. Display_val(dpy),
  1892. Window_val(win),
  1893. String_val(window_name),
  1894. String_val(icon_name),
  1895. icon_pixmap,
  1896. argv, argc,
  1897. XSizeHints_val(hints) );
  1898. for (i=0; i<argc; ++i) {
  1899. free(argv[i]);
  1900. }
  1901. free(argv);
  1902. CHECK_STATUS(XSetStandardProperties,1);
  1903. return Val_unit;
  1904. }
  1905. CAMLprim value
  1906. ml_XSetStandardProperties_bytecode( value * argv, int argn )
  1907. {
  1908. return ml_XSetStandardProperties( argv[0], argv[1], argv[2],
  1909. argv[3], argv[4], argv[5], argv[6] );
  1910. }
  1911. CAMLprim value
  1912. ml_alloc_XGCValues( value unit )
  1913. {
  1914. CAMLparam0();
  1915. CAMLlocal1(gcv);
  1916. alloc_XGCValues(gcv);
  1917. memset(XGCValues_val(gcv), 0, sizeof(XGCValues));
  1918. CAMLreturn(gcv);
  1919. }
  1920. static const unsigned long gc_valuemask_table[] = {
  1921. GCFunction,
  1922. GCPlaneMask,
  1923. GCForeground,
  1924. GCBackground,
  1925. GCLineWidth,
  1926. GCLineStyle,
  1927. GCCapStyle,
  1928. GCJoinStyle,
  1929. GCFillStyle,
  1930. GCFillRule,
  1931. GCTile,
  1932. GCStipple,
  1933. GCTileStipXOrigin,
  1934. GCTileStipYOrigin,
  1935. GCFont,
  1936. GCSubwindowMode,
  1937. GCGraphicsExposures,
  1938. GCClipXOrigin,
  1939. GCClipYOrigin,
  1940. GCClipMask,
  1941. GCDashOffset,
  1942. GCDashList,
  1943. GCArcMode,
  1944. };
  1945. static inline unsigned long
  1946. gc_valuemask_val( value mask_list )
  1947. {
  1948. unsigned long c_mask = 0;
  1949. while ( mask_list != Val_emptylist )
  1950. {
  1951. value head = Field(mask_list, 0);
  1952. c_mask |= gc_valuemask_table[Long_val(head)];
  1953. mask_list = Field(mask_list, 1);
  1954. }
  1955. return c_mask;
  1956. }
  1957. CAMLprim value
  1958. ml_XCreateGC( value dpy, value d, value valuemask, value gc_values )
  1959. {
  1960. CAMLparam4( dpy, d, valuemask, gc_values );
  1961. GC gc = XCreateGC(
  1962. Display_val(dpy),
  1963. Drawable_val(d),
  1964. gc_valuemask_val(valuemask),
  1965. XGCValues_val(gc_values)
  1966. );
  1967. if (!gc)
  1968. caml_failwith("xCreateGC: out of memory");
  1969. CAMLreturn( Val_GC_final(gc,dpy) );
  1970. }
  1971. CAMLprim value
  1972. ml_XChangeGC( value dpy, value gc, value valuemask, value gc_values )
  1973. {
  1974. //GET_STATUS
  1975. XChangeGC(
  1976. Display_val(dpy),
  1977. GC_val(gc),
  1978. gc_valuemask_val(valuemask),
  1979. XGCValues_val(gc_values)
  1980. );
  1981. //CHECK_STATUS(XChangeGC,1);
  1982. return Val_unit;
  1983. }
  1984. CAMLprim value
  1985. ml_XGetGCValues( value dpy, value gc, value valuemask )
  1986. {
  1987. CAMLparam3(dpy, gc, valuemask);
  1988. CAMLlocal1(gcv);
  1989. alloc_XGCValues(gcv);
  1990. GET_STATUS XGetGCValues(
  1991. Display_val(dpy),
  1992. GC_val(gc),
  1993. gc_valuemask_val(valuemask),
  1994. XGCValues_val(gcv)
  1995. );
  1996. CHECK_STATUS(XGetGCValues,True);
  1997. CAMLreturn(gcv);
  1998. }
  1999. static const int logical_operation_function_table[] = {
  2000. GXclear,
  2001. GXand,
  2002. GXandReverse,
  2003. GXcopy,
  2004. GXandInverted,
  2005. GXnoop,
  2006. GXxor,
  2007. GXor,
  2008. GXnor,
  2009. GXequiv,
  2010. GXinvert,
  2011. GXorReverse,
  2012. GXcopyInverted,
  2013. GXorInverted,
  2014. GXnand,
  2015. GXset
  2016. };
  2017. #define Function_val(i) (logical_operation_function_table[Long_val(i)])
  2018. static inline value Val_function(int function) {
  2019. switch (function) {
  2020. case GXclear: return Val_int(0);
  2021. case GXand: return Val_int(1);
  2022. case GXandReverse: return Val_int(2);
  2023. case GXcopy: return Val_int(3);
  2024. case GXandInverted: return Val_int(4);
  2025. case GXnoop: return Val_int(5);
  2026. case GXxor: return Val_int(6);
  2027. case GXor: return Val_int(7);
  2028. case GXnor: return Val_int(8);
  2029. case GXequiv: return Val_int(9);
  2030. case GXinvert: return Val_int(10);
  2031. case GXorReverse: return Val_int(11);
  2032. case GXcopyInverted: return Val_int(12);
  2033. case GXorInverted: return Val_int(13);
  2034. case GXnand: return Val_int(14);
  2035. case GXset: return Val_int(15);
  2036. }
  2037. return Val_int(0);
  2038. }
  2039. static const int line_style_table[] = {
  2040. LineSolid,
  2041. LineOnOffDash,
  2042. LineDoubleDash
  2043. };
  2044. #define Line_style_val(i) (line_style_table[Long_val(i)])
  2045. static inline value Val_line_style(int line_style) {
  2046. switch (line_style) {
  2047. case LineSolid: return Val_int(0);
  2048. case LineOnOffDash: return Val_int(1);
  2049. case LineDoubleDash: return Val_int(2);
  2050. }
  2051. return Val_int(0);
  2052. }
  2053. static const int cap_style_table[] = {
  2054. CapNotLast,
  2055. CapButt,
  2056. CapRound,
  2057. CapProjecting
  2058. };
  2059. #define Cap_style_val(i) (cap_style_table[Long_val(i)])
  2060. static inline value Val_cap_style(int cap_style) {
  2061. switch (cap_style) {
  2062. case CapNotLast: return Val_int(0);
  2063. case CapButt: return Val_int(1);
  2064. case CapRound: return Val_int(2);
  2065. case CapProjecting: return Val_int(3);
  2066. }
  2067. return Val_int(0);
  2068. }
  2069. static const int join_style_table[] = {
  2070. JoinMiter,
  2071. JoinRound,
  2072. JoinBevel
  2073. };
  2074. #define Join_style_val(i) (join_style_table[Long_val(i)])
  2075. static inline value Val_join_style(int join_style) {
  2076. switch (join_style) {
  2077. case JoinMiter: return Val_int(0);
  2078. case JoinRound: return Val_int(1);
  2079. case JoinBevel: return Val_int(2);
  2080. }
  2081. return Val_int(0);
  2082. }
  2083. static const int fill_style_table[] = {
  2084. FillSolid,
  2085. FillTiled,
  2086. FillStippled,
  2087. FillOpaqueStippled
  2088. };
  2089. #define Fill_style_val(i) (fill_style_table[Long_val(i)])
  2090. static inline value Val_fill_style(int fill_style) {
  2091. switch (fill_style) {
  2092. case FillSolid: return Val_int(0);
  2093. case FillTiled: return Val_int(1);
  2094. case FillStippled: return Val_int(2);
  2095. case FillOpaqueStippled: return Val_int(3);
  2096. }
  2097. return Val_int(0);
  2098. }
  2099. static const int fill_rule_table[] = {
  2100. EvenOddRule,
  2101. WindingRule
  2102. };
  2103. #define Fill_rule_val(i) (fill_rule_table[Long_val(i)])
  2104. static inline value Val_fill_rule(int fill_rule) {
  2105. switch (fill_rule) {
  2106. case EvenOddRule: return Val_int(0);
  2107. case WindingRule: return Val_int(1);
  2108. }
  2109. return Val_int(0);
  2110. }
  2111. static const int arc_mode_table[] = {
  2112. ArcChord,
  2113. ArcPieSlice
  2114. };
  2115. #define Arc_mode_val(i) (arc_mode_table[Long_val(i)])
  2116. static inline value Val_arc_mode(int arc_mode) {
  2117. switch (arc_mode) {
  2118. case ArcChord: return Val_int(0);
  2119. case ArcPieSlice: return Val_int(1);
  2120. }
  2121. return Val_int(0);
  2122. }
  2123. static const int subwindow_mode_table[] = {
  2124. ClipByChildren,
  2125. IncludeInferiors
  2126. };
  2127. #define Subwindow_mode_val(i) (subwindow_mode_table[Long_val(i)])
  2128. static inline value Val_subwindow_mode(int subwindow_mode) {
  2129. switch (subwindow_mode) {
  2130. case ClipByChildren: return Val_int(0);
  2131. case IncludeInferiors: return Val_int(1);
  2132. }
  2133. return Val_int(0);
  2134. }
  2135. #define GCVAL_SET(field_c_type, field_name, Conv_val, Val_conv, ml_type, mask) \
  2136. \
  2137. CAMLprim value \
  2138. ml_XGCValues_set_##field_name( value ml_gcv, value v ) \
  2139. { \
  2140. XGCValues * gcv; \
  2141. gcv = XGCValues_val(ml_gcv); \
  2142. gcv->field_name = Conv_val(v); \
  2143. return Val_unit; \
  2144. }
  2145. #define GCVAL_GET(field_c_type, field_name, Conv_val, Val_conv, ml_type, mask) \
  2146. \
  2147. CAMLprim value \
  2148. ml_XGCValues_get_##field_name( value ml_gcv, value v ) \
  2149. { \
  2150. XGCValues * gcv; \
  2151. gcv = XGCValues_val(ml_gcv); \
  2152. return Val_conv( gcv->field_name ); \
  2153. }
  2154. #define GCVAL_SML(field_c_type, field_name, Conv_val, Val_conv, ml_type, mask) \
  2155. external xGCValues_set_##field_name: gcv:xGCValues -> ml_type -> unit = quote(ml_XGCValues_set_##field_name)
  2156. #define GCVAL_GML(field_c_type, field_name, Conv_val, Val_conv, ml_type, mask) \
  2157. external xGCValues_get_##field_name: gcv:xGCValues -> ml_type = quote(ml_XGCValues_get_##field_name)
  2158. GCVAL_SET( unsigned long, foreground, Pixel_color_val, Val_pixel_color, pixel_color, GCForeground )
  2159. GCVAL_SET( unsigned long, background, Pixel_color_val, Val_pixel_color, pixel_color, GCBackground )
  2160. GCVAL_SET( Bool, graphics_exposures, Bool_val, Val_bool, bool, GCGraphicsExposures )
  2161. GCVAL_SET( Pixmap, tile, Pixmap_val, Val_Pixmap, pixmap, GCTile )
  2162. GCVAL_SET( int, clip_x_origin, Int_val, Val_int, int, GCClipXOrigin )
  2163. GCVAL_SET( int, clip_y_origin, Int_val, Val_int, int, GCClipYOrigin )
  2164. GCVAL_SET( int, ts_x_origin, Int_val, Val_int, int, GCTileStipXOrigin )
  2165. GCVAL_SET( int, ts_y_origin, Int_val, Val_int, int, GCTileStipYOrigin )
  2166. GCVAL_SET( int, line_style, Line_style_val, Val_line_style, line_style, GCLineStyle )
  2167. GCVAL_SET( int, cap_style, Cap_style_val, Val_cap_style, cap_style, GCCapStyle )
  2168. GCVAL_SET( int, join_style, Join_style_val, Val_join_style, join_style, GCJoinStyle )
  2169. GCVAL_SET( int, fill_style, Fill_style_val, Val_fill_style, fill_style, GCFillStyle )
  2170. GCVAL_SET( int, fill_rule, Fill_rule_val, Val_fill_rule, fill_rule, GCFillRule )
  2171. GCVAL_SET( int, function, Function_val, Val_function, logop_func, GCFunction )
  2172. GCVAL_SET( int, line_width, Int_val, Val_int, int, GCLineWidth )
  2173. GCVAL_SET( int, arc_mode, Arc_mode_val, Val_arc_mode, arc_mode, GCArcMode )
  2174. GCVAL_SET( Font, font, Font_val, Val_Font, font, GCFont )
  2175. GCVAL_SET( int, subwindow_mode, Subwindow_mode_val, Val_subwindow_mode, subwindow_mode, GCSubwindowMode )
  2176. GCVAL_GET( unsigned long, foreground, Pixel_color_val, Val_pixel_color, pixel_color, GCForeground )
  2177. GCVAL_GET( unsigned long, background, Pixel_color_val, Val_pixel_color, pixel_color, GCBackground )
  2178. GCVAL_GET( Bool, graphics_exposures, Bool_val, Val_bool, bool, GCGraphicsExposures )
  2179. GCVAL_GET( Pixmap, tile, Pixmap_val, Val_Pixmap, pixmap, GCTile )
  2180. GCVAL_GET( int, clip_x_origin, Int_val, Val_int, int, GCClipXOrigin )
  2181. GCVAL_GET( int, clip_y_origin, Int_val, Val_int, int, GCClipYOrigin )
  2182. GCVAL_GET( int, ts_x_origin, Int_val, Val_int, int, GCTileStipXOrigin )
  2183. GCVAL_GET( int, ts_y_origin, Int_val, Val_int, int, GCTileStipYOrigin )
  2184. GCVAL_GET( int, line_style, Line_style_val, Val_line_style, line_style, GCLineStyle )
  2185. GCVAL_GET( int, cap_style, Cap_style_val, Val_cap_style, cap_style, GCCapStyle )
  2186. GCVAL_GET( int, join_style, Join_style_val, Val_join_style, join_style, GCJoinStyle )
  2187. GCVAL_GET( int, fill_style, Fill_style_val, Val_fill_style, fill_style, GCFillStyle )
  2188. GCVAL_GET( int, fill_rule, Fill_rule_val, Val_fill_rule, fill_rule, GCFillRule )
  2189. GCVAL_GET( int, function, Function_val, Val_function, logop_func, GCFunction )
  2190. GCVAL_GET( int, line_width, Int_val, Val_int, int, GCLineWidth )
  2191. GCVAL_GET( int, arc_mode, Arc_mode_val, Val_arc_mode, arc_mode, GCArcMode )
  2192. GCVAL_GET( Font, font, Font_val, Val_Font, font, GCFont )
  2193. GCVAL_GET( int, subwindow_mode, Subwindow_mode_val, Val_subwindow_mode, subwindow_mode, GCSubwindowMode )
  2194. /*
  2195. | GCPlaneMask
  2196. | GCStipple
  2197. | GCClipMask
  2198. | GCDashOffset
  2199. | GCDashList
  2200. */
  2201. #if 0
  2202. XGCValues gcv;
  2203. gcv.plane_mask = 0x1;
  2204. gcv.stipple = bitmap;
  2205. gcv.clip_mask = bitmap;
  2206. gcv.dash_offset = 1;
  2207. gcv.dashes = 0xc2;
  2208. GC gc = XCreateGC(dpy, w,
  2209. GCFunction | GCPlaneMask | GCForeground | GCBackground | GCLineWidth | GCLineStyle
  2210. | GCCapStyle | GCJoinStyle | GCFillStyle | GCFillRule | GCTile | GCStipple
  2211. | GCTileStipXOrigin | GCTileStipYOrigin | GCFont | GCSubwindowMode | GCGraphicsExposures
  2212. | GCClipXOrigin | GCClipYOrigin | GCClipMask | GCDashOffset | GCDashList | GCArcMode,
  2213. &gcv);
  2214. unsigned long plane_mask;/* plane mask */
  2215. Pixmap stipple; /* stipple 1 plane pixmap for stipping */
  2216. int subwindow_mode; /* ClipByChildren, IncludeInferiors */
  2217. Pixmap clip_mask; /* bitmap clipping; other calls for rects */
  2218. int dash_offset; /* patterned/dashed line information */
  2219. char dashes;
  2220. #endif
  2221. CAMLprim value
  2222. ml_XSetForeground( value dpy, value gc, value foreground )
  2223. {
  2224. GET_STATUS XSetForeground(
  2225. Display_val(dpy),
  2226. GC_val(gc),
  2227. Pixel_color_val(foreground)
  2228. );
  2229. CHECK_STATUS(XSetForeground,1);
  2230. return Val_unit;
  2231. }
  2232. CAMLprim value
  2233. ml_XSetBackground( value dpy, value gc, value background )
  2234. {
  2235. GET_STATUS XSetBackground(
  2236. Display_val(dpy),
  2237. GC_val(gc),
  2238. Pixel_color_val(background)
  2239. );
  2240. CHECK_STATUS(XSetBackground,1);
  2241. return Val_unit;
  2242. }
  2243. CAMLprim value
  2244. ml_XSetLineAttributes( value dpy, value gc, value line_width, value line_style,
  2245. value cap_style, value join_style )
  2246. {
  2247. GET_STATUS XSetLineAttributes(
  2248. Display_val(dpy),
  2249. GC_val(gc),
  2250. UInt_val(line_width),
  2251. Line_style_val(line_style),
  2252. Cap_style_val(cap_style),
  2253. Join_style_val(join_style)
  2254. );
  2255. CHECK_STATUS(XSetLineAttributes,1);
  2256. return Val_unit;
  2257. }
  2258. CAMLprim value
  2259. ml_XSetLineAttributes_bytecode( value * argv, int argn )
  2260. {
  2261. return ml_XSetLineAttributes( argv[0], argv[1], argv[2],
  2262. argv[3], argv[4], argv[5] );
  2263. }
  2264. CAMLprim value ml_XSetFillStyle( value dpy, value gc, value fill_style )
  2265. {
  2266. XSetFillStyle(
  2267. Display_val(dpy),
  2268. GC_val(gc),
  2269. Fill_style_val(fill_style)
  2270. );
  2271. return Val_unit;
  2272. }
  2273. CAMLprim value
  2274. ml_XClearWindow( value dpy, value win )
  2275. {
  2276. GET_STATUS XClearWindow(
  2277. Display_val(dpy),
  2278. Window_val(win)
  2279. );
  2280. CHECK_STATUS(XClearWindow,1);
  2281. return Val_unit;
  2282. }
  2283. CAMLprim value
  2284. ml_XClearArea( value dpy, value win, value x, value y, value width, value height, value exposures )
  2285. {
  2286. //GET_STATUS
  2287. XClearArea(
  2288. Display_val(dpy),
  2289. Window_val(win),
  2290. Int_val(x),
  2291. Int_val(y),
  2292. UInt_val(width),
  2293. UInt_val(height),
  2294. Bool_val(exposures)
  2295. );
  2296. //CHECK_STATUS(XClearArea,1);
  2297. return Val_unit;
  2298. }
  2299. CAMLprim value
  2300. ml_XClearArea_bytecode( value * argv, int argn )
  2301. {
  2302. return ml_XClearArea( argv[0], argv[1], argv[2],
  2303. argv[3], argv[4], argv[5], argv[6] );
  2304. }
  2305. /*
  2306. TODO: Max number of elements:
  2307. XDrawLines() points: XMaxRequestSize(dpy) - 3
  2308. XFillPolygon() points: XMaxRequestSize(dpy) - 4
  2309. XDrawSegments() segments: (XMaxRequestSize(dpy) - 3) / 2
  2310. XDrawRectangles() rectangles: (XMaxRequestSize(dpy) - 3) / 2
  2311. XFillRectangles() rectangles: (XMaxRequestSize(dpy) - 3) / 2
  2312. XDrawArcs() or XFillArcs() arcs: (XMaxRequestSize(dpy) - 3) / 3
  2313. */
  2314. CAMLprim value
  2315. ml_XDrawArc( value dpy, value d, value gc, value x, value y,
  2316. value width, value height, value angle1, value angle2 )
  2317. {
  2318. GET_STATUS XDrawArc(
  2319. Display_val(dpy),
  2320. Drawable_val(d),
  2321. GC_val(gc),
  2322. Int_val(x),
  2323. Int_val(y),
  2324. UInt_val(width),
  2325. UInt_val(height),
  2326. Int_val(angle1),
  2327. Int_val(angle2)
  2328. );
  2329. CHECK_STATUS(XDrawArc, 1);
  2330. return Val_unit;
  2331. }
  2332. CAMLprim value
  2333. ml_XDrawArc_bytecode( value * argv, int argn )
  2334. {
  2335. return ml_XDrawArc( argv[0], argv[1], argv[2], argv[3],
  2336. argv[4], argv[5], argv[6], argv[7], argv[8] );
  2337. }
  2338. CAMLprim value
  2339. ml_XDrawArcs( value dpy, value d, value gc, value ml_arcs )
  2340. {
  2341. int i, narcs = Wosize_val(ml_arcs);
  2342. XArc * arcs = malloc(narcs * sizeof(XArc));
  2343. for (i=0; i<narcs; ++i) {
  2344. value a = Field(ml_arcs, i);
  2345. arcs[i].x = Int_val(Field(a,0));
  2346. arcs[i].y = Int_val(Field(a,1));
  2347. arcs[i].width = UInt_val(Field(a,2));
  2348. arcs[i].height = UInt_val(Field(a,3));
  2349. arcs[i].angle1 = Int_val(Field(a,4));
  2350. arcs[i].angle2 = Int_val(Field(a,5));
  2351. }
  2352. GET_STATUS XDrawArcs(
  2353. Display_val(dpy),
  2354. Drawable_val(d),
  2355. GC_val(gc),
  2356. arcs,
  2357. narcs
  2358. );
  2359. free(arcs);
  2360. CHECK_STATUS(XDrawArcs,1);
  2361. return Val_unit;
  2362. }
  2363. CAMLprim value
  2364. ml_XDrawImageString( value dpy, value d, value gc, value x, value y, value str )
  2365. {
  2366. GET_STATUS XDrawImageString(
  2367. Display_val(dpy),
  2368. Drawable_val(d),
  2369. GC_val(gc),
  2370. Int_val(x),
  2371. Int_val(y),
  2372. String_val(str),
  2373. caml_string_length(str)
  2374. );
  2375. CHECK_STATUS(XDrawImageString, 0);
  2376. return Val_unit;
  2377. }
  2378. CAMLprim value
  2379. ml_XDrawImageString_bytecode( value * argv, int argn )
  2380. {
  2381. return ml_XDrawImageString( argv[0], argv[1], argv[2],
  2382. argv[3], argv[4], argv[5] );
  2383. }
  2384. CAMLprim value
  2385. ml_alloc_XChar2b( value b2 )
  2386. {
  2387. CAMLparam1(b2);
  2388. CAMLlocal1(xchar2b);
  2389. XChar2b *char16;
  2390. alloc_XChar2b(xchar2b);
  2391. char16 = XChar2b_val(xchar2b);
  2392. char16->byte1 = (unsigned char) Long_val(Field(b2,0));
  2393. char16->byte2 = (unsigned char) Long_val(Field(b2,1));
  2394. CAMLreturn(xchar2b);
  2395. }
  2396. CAMLprim value
  2397. ml_alloc_XChar2b_string( value b2_string )
  2398. {
  2399. CAMLparam1(b2_string);
  2400. CAMLlocal2(ret, xchar2b_str);
  2401. XChar2b *char16;
  2402. long i, n;
  2403. n = Wosize_val(b2_string);
  2404. alloc_n_XChar2b(xchar2b_str, n);
  2405. char16 = XChar2b_ptr_val(xchar2b_str);
  2406. for (i=0; i < n; ++i)
  2407. {
  2408. value b2 = Field(b2_string, i);
  2409. char16[i].byte1 = (unsigned char) Long_val(Field(b2,0));
  2410. char16[i].byte2 = (unsigned char) Long_val(Field(b2,1));
  2411. }
  2412. ret = caml_alloc(2, 0);
  2413. Store_field(ret, 0, xchar2b_str);
  2414. Store_field(ret, 1, Val_long(n) );
  2415. CAMLreturn(ret);
  2416. }
  2417. CAMLprim value
  2418. ml_XDrawImageString16( value dpy, value d, value gc, value x, value y, value xchar2b_string )
  2419. {
  2420. GET_STATUS XDrawImageString16(
  2421. Display_val(dpy),
  2422. Drawable_val(d),
  2423. GC_val(gc),
  2424. Int_val(x),
  2425. Int_val(y),
  2426. XChar2b_string_val(xchar2b_string),
  2427. XChar2b_string_length(xchar2b_string)
  2428. );
  2429. CHECK_STATUS(XDrawImageString16,0);
  2430. return Val_unit;
  2431. }
  2432. CAMLprim value
  2433. ml_XDrawImageString16_bytecode( value * argv, int argn )
  2434. {
  2435. return ml_XDrawImageString16( argv[0], argv[1], argv[2],
  2436. argv[3], argv[4], argv[5] );
  2437. }
  2438. CAMLprim value
  2439. ml_XDrawLine( value dpy, value d, value gc, value x1, value y1, value x2, value y2 )
  2440. {
  2441. GET_STATUS XDrawLine(
  2442. Display_val(dpy),
  2443. Drawable_val(d),
  2444. GC_val(gc),
  2445. Int_val(x1),
  2446. Int_val(y1),
  2447. Int_val(x2),
  2448. Int_val(y2)
  2449. );
  2450. CHECK_STATUS(XDrawLine,1);
  2451. return Val_unit;
  2452. }
  2453. CAMLprim value
  2454. ml_XDrawLine_bytecode( value * argv, int argn )
  2455. {
  2456. return ml_XDrawLine( argv[0], argv[1], argv[2],
  2457. argv[3], argv[4], argv[5], argv[6] );
  2458. }
  2459. static const int coordinate_mode_table[] = {
  2460. CoordModeOrigin,
  2461. CoordModePrevious,
  2462. };
  2463. CAMLprim value
  2464. ml_XDrawLines( value dpy, value d, value gc, value ml_points, value ml_mode )
  2465. {
  2466. int mode = coordinate_mode_table[ Long_val(ml_mode) ];
  2467. int i, npoints = Wosize_val(ml_points);
  2468. XPoint * points = malloc(npoints * sizeof(XPoint));
  2469. for (i=0; i<npoints; ++i)
  2470. {
  2471. value pnt = Field(ml_points, i);
  2472. points[i].x = Long_val(Field(pnt, 0));
  2473. points[i].y = Long_val(Field(pnt, 1));
  2474. }
  2475. GET_STATUS XDrawLines(
  2476. Display_val(dpy),
  2477. Drawable_val(d),
  2478. GC_val(gc),
  2479. points,
  2480. npoints,
  2481. mode
  2482. );
  2483. free(points);
  2484. CHECK_STATUS(XDrawLines,1);
  2485. return Val_unit;
  2486. }
  2487. CAMLprim value
  2488. ml_XDrawPoint( value dpy, value d, value gc, value x, value y )
  2489. {
  2490. GET_STATUS XDrawPoint(
  2491. Display_val(dpy),
  2492. Drawable_val(d),
  2493. GC_val(gc),
  2494. Int_val(x),
  2495. Int_val(y)
  2496. );
  2497. CHECK_STATUS(XDrawPoint,1);
  2498. return Val_unit;
  2499. }
  2500. CAMLprim value
  2501. ml_XDrawPoints( value dpy, value d, value gc, value ml_points, value ml_mode )
  2502. {
  2503. int mode = coordinate_mode_table[ Long_val(ml_mode) ];
  2504. int i, npoints = Wosize_val(ml_points);
  2505. XPoint * points = malloc(npoints * sizeof(XPoint));
  2506. for (i=0; i<npoints; ++i)
  2507. {
  2508. value pnt = Field(ml_points, i);
  2509. points[i].x = Long_val(Field(pnt, 0));
  2510. points[i].y = Long_val(Field(pnt, 1));
  2511. }
  2512. GET_STATUS XDrawPoints(
  2513. Display_val(dpy),
  2514. Drawable_val(d),
  2515. GC_val(gc),
  2516. points,
  2517. npoints,
  2518. mode
  2519. );
  2520. CHECK_STATUS(XDrawPoints,1);
  2521. return Val_unit;
  2522. }
  2523. CAMLprim value
  2524. ml_XDrawRectangle( value dpy, value d, value gc, value x, value y,
  2525. value width, value height )
  2526. {
  2527. GET_STATUS XDrawRectangle(
  2528. Display_val(dpy),
  2529. Drawable_val(d),
  2530. GC_val(gc),
  2531. Int_val(x),
  2532. Int_val(y),
  2533. UInt_val(width),
  2534. UInt_val(height)
  2535. );
  2536. CHECK_STATUS(XDrawRectangle, 1);
  2537. return Val_unit;
  2538. }
  2539. CAMLprim value
  2540. ml_XDrawRectangle_bytecode( value * argv, int argn )
  2541. {
  2542. return ml_XDrawRectangle( argv[0], argv[1], argv[2],
  2543. argv[3], argv[4], argv[5], argv[6] );
  2544. }
  2545. CAMLprim value
  2546. ml_XDrawRectangles( value dpy, value d, value gc, value ml_rectangles )
  2547. {
  2548. int i, nrectangles = Wosize_val(ml_rectangles);
  2549. XRectangle * rectangles = malloc(nrectangles * sizeof(XRectangle));
  2550. for (i=0; i<nrectangles; ++i) {
  2551. value rect = Field(ml_rectangles, i);
  2552. rectangles[i].x = Int_val(Field(rect,0));
  2553. rectangles[i].y = Int_val(Field(rect,1));
  2554. rectangles[i].width = UInt_val(Field(rect,2));
  2555. rectangles[i].height = UInt_val(Field(rect,3));
  2556. }
  2557. GET_STATUS XDrawRectangles(
  2558. Display_val(dpy),
  2559. Drawable_val(d),
  2560. GC_val(gc),
  2561. rectangles,
  2562. nrectangles
  2563. );
  2564. free(rectangles);
  2565. CHECK_STATUS(XDrawRectangles,1);
  2566. return Val_unit;
  2567. }
  2568. CAMLprim value
  2569. ml_XDrawSegments( value dpy, value d, value gc, value ml_segments )
  2570. {
  2571. XSegment* segments;
  2572. int nsegments = Wosize_val(ml_segments);
  2573. int i;
  2574. segments = malloc(nsegments * sizeof(XSegment));
  2575. for (i=0; i<nsegments; ++i) {
  2576. value seg = Field(ml_segments, i);
  2577. segments[i].x1 = Int_val(Field(seg,0));
  2578. segments[i].y1 = Int_val(Field(seg,1));
  2579. segments[i].x2 = Int_val(Field(seg,2));
  2580. segments[i].y2 = Int_val(Field(seg,3));
  2581. }
  2582. GET_STATUS XDrawSegments(
  2583. Display_val(dpy),
  2584. Drawable_val(d),
  2585. GC_val(gc),
  2586. segments,
  2587. nsegments
  2588. );
  2589. free(segments);
  2590. CHECK_STATUS(XDrawSegments,1);
  2591. return Val_unit;
  2592. }
  2593. CAMLprim value
  2594. ml_XDrawString( value dpy, value d, value gc, value x, value y, value str )
  2595. {
  2596. GET_STATUS XDrawString(
  2597. Display_val(dpy),
  2598. Drawable_val(d),
  2599. GC_val(gc),
  2600. Int_val(x),
  2601. Int_val(y),
  2602. String_val(str),
  2603. caml_string_length(str)
  2604. );
  2605. CHECK_STATUS(XDrawString, 0);
  2606. return Val_unit;
  2607. }
  2608. CAMLprim value
  2609. ml_XDrawString_bytecode( value * argv, int argn )
  2610. {
  2611. return ml_XDrawString( argv[0], argv[1], argv[2],
  2612. argv[3], argv[4], argv[5] );
  2613. }
  2614. CAMLprim value
  2615. ml_XDrawString16( value dpy, value d, value gc, value x, value y, value xchar2b_string )
  2616. {
  2617. GET_STATUS XDrawString16(
  2618. Display_val(dpy),
  2619. Drawable_val(d),
  2620. GC_val(gc),
  2621. Int_val(x),
  2622. Int_val(y),
  2623. XChar2b_string_val(xchar2b_string),
  2624. XChar2b_string_length(xchar2b_string)
  2625. );
  2626. CHECK_STATUS(XDrawString16, 0);
  2627. return Val_unit;
  2628. }
  2629. CAMLprim value
  2630. ml_XDrawString16_bytecode( value * argv, int argn )
  2631. {
  2632. return ml_XDrawString16( argv[0], argv[1], argv[2],
  2633. argv[3], argv[4], argv[5] );
  2634. }
  2635. /*
  2636. int XDrawText(
  2637. Display* display,
  2638. Drawable d,
  2639. GC gc,
  2640. int x,
  2641. int y,
  2642. XTextItem* items,
  2643. int nitems
  2644. );
  2645. int XDrawText16(
  2646. Display* display,
  2647. Drawable d,
  2648. GC gc,
  2649. int x,
  2650. int y,
  2651. XTextItem16* items,
  2652. int nitems
  2653. );
  2654. */
  2655. CAMLprim value
  2656. ml_XFillArc( value dpy, value d, value gc, value x, value y,
  2657. value width, value height, value angle1, value angle2 )
  2658. {
  2659. GET_STATUS XFillArc(
  2660. Display_val(dpy),
  2661. Drawable_val(d),
  2662. GC_val(gc),
  2663. Int_val(x),
  2664. Int_val(y),
  2665. UInt_val(width),
  2666. UInt_val(height),
  2667. Int_val(angle1),
  2668. Int_val(angle2)
  2669. );
  2670. CHECK_STATUS(XFillArc, 1);
  2671. return Val_unit;
  2672. }
  2673. CAMLprim value
  2674. ml_XFillArc_bytecode( value * argv, int argn )
  2675. {
  2676. return ml_XFillArc( argv[0], argv[1], argv[2], argv[3],
  2677. argv[4], argv[5], argv[6], argv[7], argv[8] );
  2678. }
  2679. CAMLprim value
  2680. ml_XFillArcs( value dpy, value d, value gc, value ml_arcs )
  2681. {
  2682. int i, narcs = Wosize_val(ml_arcs);
  2683. XArc * arcs = malloc(narcs * sizeof(XArc));
  2684. for (i=0; i<narcs; ++i) {
  2685. value a = Field(ml_arcs, i);
  2686. arcs[i].x = Int_val(Field(a,0));
  2687. arcs[i].y = Int_val(Field(a,1));
  2688. arcs[i].width = UInt_val(Field(a,2));
  2689. arcs[i].height = UInt_val(Field(a,3));
  2690. arcs[i].angle1 = Int_val(Field(a,4));
  2691. arcs[i].angle2 = Int_val(Field(a,5));
  2692. }
  2693. GET_STATUS XFillArcs(
  2694. Display_val(dpy),
  2695. Drawable_val(d),
  2696. GC_val(gc),
  2697. arcs,
  2698. narcs
  2699. );
  2700. free(arcs);
  2701. CHECK_STATUS(XFillArcs,1);
  2702. return Val_unit;
  2703. }
  2704. static const int shape_kind_table[] = {
  2705. Complex,
  2706. Nonconvex,
  2707. Convex,
  2708. };
  2709. CAMLprim value
  2710. ml_XFillPolygon(
  2711. value dpy,
  2712. value d,
  2713. value gc,
  2714. value ml_points,
  2715. value ml_shape,
  2716. value ml_mode )
  2717. {
  2718. int shape = shape_kind_table[ Long_val(ml_shape) ];
  2719. int mode = coordinate_mode_table[ Long_val(ml_mode) ];
  2720. int i, npoints = Wosize_val(ml_points);
  2721. XPoint * points = malloc(npoints * sizeof(XPoint));
  2722. for (i=0; i<npoints; ++i)
  2723. {
  2724. value pnt = Field(ml_points, i);
  2725. points[i].x = Long_val(Field(pnt, 0));
  2726. points[i].y = Long_val(Field(pnt, 1));
  2727. }
  2728. GET_STATUS XFillPolygon(
  2729. Display_val(dpy),
  2730. Drawable_val(d),
  2731. GC_val(gc),
  2732. points,
  2733. npoints,
  2734. shape,
  2735. mode
  2736. );
  2737. free(points);
  2738. CHECK_STATUS(XFillPolygon,1);
  2739. return Val_unit;
  2740. }
  2741. CAMLprim value
  2742. ml_XFillPolygon_bytecode( value * argv, int argn )
  2743. {
  2744. return ml_XFillPolygon( argv[0], argv[1], argv[2],
  2745. argv[3], argv[4], argv[5] );
  2746. }
  2747. CAMLprim value
  2748. ml_XFillRectangle( value dpy, value d, value gc, value x, value y,
  2749. value width, value height )
  2750. {
  2751. GET_STATUS XFillRectangle(
  2752. Display_val(dpy),
  2753. Drawable_val(d),
  2754. GC_val(gc),
  2755. Int_val(x),
  2756. Int_val(y),
  2757. UInt_val(width),
  2758. UInt_val(height)
  2759. );
  2760. CHECK_STATUS(XFillRectangle, 1);
  2761. return Val_unit;
  2762. }
  2763. CAMLprim value
  2764. ml_XFillRectangle_bytecode( value * argv, int argn )
  2765. {
  2766. return ml_XFillRectangle( argv[0], argv[1], argv[2],
  2767. argv[3], argv[4], argv[5], argv[6] );
  2768. }
  2769. CAMLprim value
  2770. ml_XFillRectangles( value dpy, value d, value gc, value ml_rectangles )
  2771. {
  2772. int i, nrectangles = Wosize_val(ml_rectangles);
  2773. XRectangle * rectangles = malloc(nrectangles * sizeof(XRectangle));
  2774. for (i=0; i<nrectangles; ++i) {
  2775. value rect = Field(ml_rectangles, i);
  2776. rectangles[i].x = Int_val(Field(rect,0));
  2777. rectangles[i].y = Int_val(Field(rect,1));
  2778. rectangles[i].width = UInt_val(Field(rect,2));
  2779. rectangles[i].height = UInt_val(Field(rect,3));
  2780. }
  2781. GET_STATUS XFillRectangles(
  2782. Display_val(dpy),
  2783. Drawable_val(d),
  2784. GC_val(gc),
  2785. rectangles,
  2786. nrectangles
  2787. );
  2788. free(rectangles);
  2789. CHECK_STATUS(XFillRectangles,1);
  2790. return Val_unit;
  2791. }
  2792. CAMLprim value
  2793. ml_XCopyArea( value dpy,
  2794. value src,
  2795. value dest,
  2796. value gc,
  2797. value src_x,
  2798. value src_y,
  2799. value width,
  2800. value height,
  2801. value dest_x,
  2802. value dest_y )
  2803. {
  2804. GET_STATUS XCopyArea(
  2805. Display_val(dpy),
  2806. Drawable_val(src),
  2807. Drawable_val(dest),
  2808. GC_val(gc),
  2809. Int_val(src_x),
  2810. Int_val(src_y),
  2811. UInt_val(width),
  2812. UInt_val(height),
  2813. Int_val(dest_x),
  2814. Int_val(dest_y)
  2815. );
  2816. CHECK_STATUS(XCopyArea,1);
  2817. return Val_unit;
  2818. }
  2819. CAMLprim value
  2820. ml_XCopyArea_bytecode( value * argv, int argn )
  2821. {
  2822. return ml_XCopyArea( argv[0], argv[1], argv[2], argv[3], argv[4],
  2823. argv[5], argv[6], argv[7], argv[8], argv[9] );
  2824. }
  2825. CAMLprim value
  2826. ml_XCreatePixmap( value dpy,
  2827. value dbl,
  2828. value width,
  2829. value height,
  2830. value depth )
  2831. {
  2832. Pixmap pixmap = XCreatePixmap(
  2833. Display_val(dpy),
  2834. Drawable_val(dbl),
  2835. UInt_val(width),
  2836. UInt_val(height),
  2837. UInt_val(depth)
  2838. );
  2839. return Val_Pixmap(pixmap);
  2840. }
  2841. CAMLprim value
  2842. ml_XFreePixmap( value dpy, value pixmap )
  2843. {
  2844. GET_STATUS XFreePixmap(
  2845. Display_val(dpy),
  2846. Pixmap_val(pixmap)
  2847. );
  2848. CHECK_STATUS(XFreePixmap,1);
  2849. return Val_unit;
  2850. }
  2851. CAMLprim value
  2852. ml_XCreateBitmapFromData( value dpy, value dbl, value data, value width, value height )
  2853. {
  2854. unsigned int _width = UInt_val(width);
  2855. unsigned int _height = UInt_val(height);
  2856. unsigned int len = caml_string_length(data);
  2857. if (len < (_width * _height) / 8) {
  2858. caml_invalid_argument("xCreateBitmapFromData");
  2859. }
  2860. Pixmap pixmap = XCreateBitmapFromData(
  2861. Display_val(dpy),
  2862. Drawable_val(dbl),
  2863. String_val(data),
  2864. _width,
  2865. _height
  2866. );
  2867. return Val_Pixmap(pixmap);
  2868. }
  2869. CAMLprim value
  2870. ml_XCreatePixmapCursor( value dpy, value source, value mask,
  2871. value foreground, value background, value x, value y )
  2872. {
  2873. Cursor cur = XCreatePixmapCursor(
  2874. Display_val(dpy),
  2875. Pixmap_val(source),
  2876. Pixmap_val(mask),
  2877. XColor_val(foreground),
  2878. XColor_val(background),
  2879. UInt_val(x),
  2880. UInt_val(y)
  2881. );
  2882. return Val_Cursor(cur);
  2883. }
  2884. CAMLprim value
  2885. ml_XCreatePixmapCursor_bytecode( value * argv, int argn )
  2886. {
  2887. return ml_XCreatePixmapCursor( argv[0], argv[1], argv[2],
  2888. argv[3], argv[4], argv[5], argv[6] );
  2889. }
  2890. CAMLprim value
  2891. ml_XQueryBestTile( value dpy, value dbl, value width, value height )
  2892. {
  2893. CAMLparam1(dpy);
  2894. CAMLlocal1(size);
  2895. unsigned int width_return, height_return;
  2896. GET_STATUS XQueryBestTile(
  2897. Display_val(dpy),
  2898. Drawable_val(dbl),
  2899. UInt_val(width),
  2900. UInt_val(height),
  2901. &width_return,
  2902. &height_return
  2903. );
  2904. CHECK_STATUS(XQueryBestTile,1);
  2905. size = caml_alloc(2, 0);
  2906. Store_field( size, 0, Val_uint(width_return) );
  2907. Store_field( size, 1, Val_uint(height_return) );
  2908. CAMLreturn(size);
  2909. }
  2910. CAMLprim value
  2911. ml_XListPixmapFormats( value dpy )
  2912. {
  2913. CAMLparam1(dpy);
  2914. CAMLlocal2(arr, v);
  2915. int i, count = 0;
  2916. XPixmapFormatValues * pfv = NULL;
  2917. pfv = XListPixmapFormats(
  2918. Display_val(dpy),
  2919. &count
  2920. );
  2921. if (pfv == NULL)
  2922. caml_failwith("xListPixmapFormats: out of memory");
  2923. arr = caml_alloc(count, 0);
  2924. for (i=0; i<count; ++i)
  2925. {
  2926. v = caml_alloc(3, 0);
  2927. Store_field(v, 0, Val_int(pfv[i].depth));
  2928. Store_field(v, 1, Val_int(pfv[i].bits_per_pixel));
  2929. Store_field(v, 2, Val_int(pfv[i].scanline_pad));
  2930. Store_field(arr, i, v);
  2931. }
  2932. XFree(pfv);
  2933. CAMLreturn(arr);
  2934. }
  2935. /* XImage */
  2936. CAMLprim value
  2937. ml_XImageByteOrder( value dpy )
  2938. {
  2939. int order = _xImageByteOrder( Display_val(dpy) );
  2940. switch (order) {
  2941. case LSBFirst: return Val_int(0);
  2942. case MSBFirst: return Val_int(1);
  2943. }
  2944. caml_failwith("xImageByteOrder");
  2945. return Val_unit;
  2946. }
  2947. static const int ximage_format_table[] = {
  2948. XYBitmap,
  2949. XYPixmap,
  2950. ZPixmap,
  2951. };
  2952. #define XImage_format_val(i) (ximage_format_table[Long_val(i)])
  2953. #define Val_XImage(d) ((value)(d))
  2954. #define XImage_val(v) ((XImage *)(v))
  2955. CAMLprim value
  2956. ml_XCreateImage( value dpy, value visual, value depth, value format, value offset,
  2957. value data, value width, value height, value bitmap_pad, value bytes_per_line )
  2958. {
  2959. char* _data;
  2960. _data = (char *)((Tag_val(data) == String_tag)? (String_val(data)) : (Caml_ba_data_val(data)));
  2961. XImage *ximage = XCreateImage(
  2962. Display_val(dpy),
  2963. Visual_val(visual),
  2964. Int_val(depth),
  2965. XImage_format_val(format),
  2966. Int_val(offset),
  2967. _data,
  2968. UInt_val(width),
  2969. UInt_val(height),
  2970. Int_val(bitmap_pad), /* XXX */
  2971. Int_val(bytes_per_line) /* XXX */
  2972. );
  2973. return Val_XImage(ximage);
  2974. }
  2975. CAMLprim value
  2976. ml_XCreateImage_bytecode( value * argv, int argn )
  2977. {
  2978. return ml_XCreateImage( argv[0], argv[1], argv[2], argv[3], argv[4],
  2979. argv[5], argv[6], argv[7], argv[8], argv[9] );
  2980. }
  2981. CAMLprim value
  2982. ml_XDestroyImage( value ximage )
  2983. {
  2984. //GET_STATUS
  2985. XDestroyImage(
  2986. XImage_val(ximage)
  2987. );
  2988. //CHECK_STATUS(XDestroyImage,1);
  2989. return Val_unit;
  2990. }
  2991. CAMLprim value
  2992. ml_XSubImage( value ximage, value x, value y, value width, value height )
  2993. {
  2994. XImage *sub_image = XSubImage(
  2995. XImage_val(ximage),
  2996. Int_val(x),
  2997. Int_val(y),
  2998. UInt_val(width),
  2999. UInt_val(height)
  3000. );
  3001. return Val_XImage(sub_image);
  3002. }
  3003. CAMLprim value
  3004. ml_XAllPlanes( value unit )
  3005. {
  3006. return Val_ulong(XAllPlanes()); // TODO: maybe switch to an ocaml int32
  3007. }
  3008. CAMLprim value
  3009. ml_XGetImage( value dpy, value d, value x, value y,
  3010. value width, value height, value plane_mask, value _format )
  3011. {
  3012. XImage *ximage;
  3013. int format = XImage_format_val(_format);
  3014. if (format == XYBitmap)
  3015. caml_invalid_argument("xGetImage: format should be XYPixmap or ZPixmap");
  3016. /*
  3017. plane_mask represents an (unsigned long) and
  3018. OCaml ints are C (long) and XAllPlanes()
  3019. returns all bits set to 1 so even the signed
  3020. bit. So we can not use the macro ULong_val()
  3021. but Long_val()
  3022. XXX: Maybe we should use an ocaml int32 ?
  3023. */
  3024. ximage = XGetImage(
  3025. Display_val(dpy),
  3026. Drawable_val(d),
  3027. Int_val(x),
  3028. Int_val(y),
  3029. UInt_val(width),
  3030. UInt_val(height),
  3031. ULong_val(plane_mask), // ULong_val(plane_mask),
  3032. format
  3033. );
  3034. if(ximage == NULL) {
  3035. caml_failwith("XGetImage: xImage could not be created");
  3036. }
  3037. return Val_XImage(ximage);
  3038. }
  3039. CAMLprim value
  3040. ml_XGetImage_bytecode( value * argv, int argn )
  3041. {
  3042. return ml_XGetImage( argv[0], argv[1], argv[2], argv[3],
  3043. argv[4], argv[5], argv[6], argv[7] );
  3044. }
  3045. /* TODO:
  3046. XImage *XGetSubImage(
  3047. Display* display,
  3048. Drawable d,
  3049. int x,
  3050. int y,
  3051. unsigned int width,
  3052. unsigned int height,
  3053. unsigned long plane_mask,
  3054. int format,
  3055. XImage* dest_image,
  3056. int dest_x,
  3057. int dest_y
  3058. );
  3059. */
  3060. CAMLprim value
  3061. ml_XImage_data_str( value ximage )
  3062. {
  3063. CAMLparam1(ximage);
  3064. CAMLlocal1(ml_data);
  3065. XImage *xim = XImage_val(ximage);
  3066. unsigned long size = /* xim->width * */ xim->height * xim->bytes_per_line;
  3067. void *data_ptr = (void*) (&(xim->data[0]));
  3068. ml_data = caml_alloc_string(size);
  3069. memcpy( String_val(ml_data), data_ptr, size );
  3070. CAMLreturn(ml_data);
  3071. }
  3072. CAMLprim value
  3073. ml_XImage_data_ba( value ximage )
  3074. {
  3075. CAMLparam1(ximage);
  3076. CAMLlocal1(img_ba);
  3077. XImage *xim = XImage_val(ximage);
  3078. unsigned long size = /* xim->width * */ xim->height * xim->bytes_per_line;
  3079. void *data_ptr = (void*) (&(xim->data[0]));
  3080. long dims[3];
  3081. dims[0] = xim->width;
  3082. dims[1] = xim->height;
  3083. //dims[2] = xim->depth; /* TODO: DEBUG ME! */
  3084. dims[2] = xim->bytes_per_line / xim->width;
  3085. img_ba = caml_ba_alloc(CAML_BA_UINT8 | CAML_BA_C_LAYOUT, 3, NULL, dims);
  3086. memcpy( Caml_ba_data_val(img_ba), data_ptr, size );
  3087. CAMLreturn(img_ba);
  3088. }
  3089. CAMLprim value
  3090. ml_XGetPixel( value ximage, value x, value y )
  3091. {
  3092. unsigned long pixel = XGetPixel(
  3093. XImage_val(ximage),
  3094. Int_val(x),
  3095. Int_val(y)
  3096. );
  3097. return Val_pixel_color(pixel);
  3098. }
  3099. CAMLprim value
  3100. ml_XPutPixel( value ximage, value x, value y, value pixel )
  3101. {
  3102. //GET_STATUS
  3103. XPutPixel(
  3104. XImage_val(ximage),
  3105. Int_val(x),
  3106. Int_val(y),
  3107. Pixel_color_val(pixel)
  3108. );
  3109. //CHECK_STATUS(XPutPixel,1);
  3110. return Val_unit;
  3111. }
  3112. CAMLprim value
  3113. ml_XAddPixel( value ximage, value v )
  3114. {
  3115. //GET_STATUS
  3116. XAddPixel(
  3117. XImage_val(ximage),
  3118. Long_val(v)
  3119. );
  3120. //CHECK_STATUS(XAddPixel,0);
  3121. return Val_unit;
  3122. }
  3123. CAMLprim value
  3124. ml_XPutImage( value dpy, value d, value gc, value ximage,
  3125. value src_x, value src_y, value dest_x, value dest_y,
  3126. value width, value height )
  3127. {
  3128. //GET_STATUS
  3129. XPutImage(
  3130. Display_val(dpy),
  3131. Drawable_val(d),
  3132. GC_val(gc),
  3133. XImage_val(ximage),
  3134. Int_val(src_x),
  3135. Int_val(src_y),
  3136. Int_val(dest_x),
  3137. Int_val(dest_y),
  3138. UInt_val(width),
  3139. UInt_val(height)
  3140. );
  3141. //CHECK_STATUS(XPutImage,0);
  3142. return Val_unit;
  3143. }
  3144. CAMLprim value
  3145. ml_XPutImage_bytecode( value * argv, int argn )
  3146. {
  3147. return ml_XPutImage( argv[0], argv[1], argv[2], argv[3], argv[4],
  3148. argv[5], argv[6], argv[7], argv[8], argv[9] );
  3149. }
  3150. /* Font */
  3151. CAMLprim value
  3152. ml_XLoadFont( value dpy, value name )
  3153. {
  3154. Font font = XLoadFont(
  3155. Display_val(dpy),
  3156. String_val(name) );
  3157. return Val_Font(font);
  3158. }
  3159. /* Setting and Retrieving the Font Search Path */
  3160. CAMLprim value
  3161. ml_XSetFontPath( value dpy, value ml_directories )
  3162. {
  3163. char** directories;
  3164. int ndirs, i;
  3165. ndirs = Wosize_val(ml_directories);
  3166. directories = malloc(ndirs * sizeof(char*));
  3167. for (i=0; i < ndirs; i++)
  3168. {
  3169. directories[i] = String_val(Field(ml_directories, i));
  3170. }
  3171. GET_STATUS XSetFontPath(
  3172. Display_val(dpy),
  3173. directories,
  3174. ndirs
  3175. );
  3176. free(directories);
  3177. CHECK_STATUS(XSetFontPath,1);
  3178. return Val_unit;
  3179. }
  3180. CAMLprim value
  3181. ml_XGetFontPath( value dpy )
  3182. {
  3183. CAMLlocal1(ml_paths);
  3184. int npaths;
  3185. char **paths = XGetFontPath(
  3186. Display_val(dpy),
  3187. &npaths
  3188. );
  3189. ml_paths = caml_copy_string_array_n(paths, npaths);
  3190. XFreeFontPath(paths);
  3191. return ml_paths;
  3192. }
  3193. CAMLprim value
  3194. ml_XListFonts( value dpy, value pattern, value maxnames )
  3195. {
  3196. CAMLlocal1(ml_list);
  3197. int actual_count;
  3198. char **list = XListFonts(
  3199. Display_val(dpy),
  3200. String_val(pattern),
  3201. Int_val(maxnames),
  3202. &actual_count
  3203. );
  3204. if (list == NULL) {
  3205. caml_failwith("no matching font names");
  3206. }
  3207. ml_list = caml_copy_string_array_n(list, actual_count);
  3208. XFreeFontNames(list);
  3209. return ml_list;
  3210. }
  3211. #if 0
  3212. TODO:
  3213. char **XListFontsWithInfo(
  3214. Display* /* display */,
  3215. _Xconst char* /* pattern */,
  3216. int /* maxnames */,
  3217. int* /* count_return */,
  3218. XFontStruct** /* info_return */
  3219. );
  3220. char **XListExtensions(
  3221. Display* /* display */,
  3222. int* /* nextensions_return */
  3223. );
  3224. #endif
  3225. /* XEvent */
  3226. CAMLprim value
  3227. ml_alloc_XEvent( value unit )
  3228. {
  3229. CAMLparam0();
  3230. CAMLlocal1(event);
  3231. alloc_XEvent(event);
  3232. memset(XEvent_val(event), 0, sizeof(XEvent));
  3233. CAMLreturn(event);
  3234. }
  3235. CAMLprim value
  3236. ml_XNextEvent( value dpy, value event )
  3237. {
  3238. GET_STATUS XNextEvent(
  3239. Display_val(dpy),
  3240. XEvent_val(event) );
  3241. CHECK_STATUS(XNextEvent, 0);
  3242. return Val_unit;
  3243. }
  3244. CAMLprim value
  3245. ml_XPeekEvent( value dpy, value event )
  3246. {
  3247. GET_STATUS XPeekEvent(
  3248. Display_val(dpy),
  3249. XEvent_val(event) );
  3250. CHECK_STATUS(XPeekEvent, 1);
  3251. return Val_unit;
  3252. }
  3253. CAMLprim value
  3254. ml_XNextEvent_fun( value dpy )
  3255. {
  3256. CAMLparam1( dpy );
  3257. CAMLlocal1( ml_event );
  3258. XEvent event;
  3259. GET_STATUS XNextEvent(
  3260. Display_val(dpy),
  3261. &event );
  3262. CHECK_STATUS(XNextEvent, 0);
  3263. copy_XEvent( event, ml_event );
  3264. CAMLreturn( ml_event );
  3265. }
  3266. CAMLprim value
  3267. ml_XNextEvent_fun_2( value dpy ) // TODO test me
  3268. {
  3269. CAMLparam1(dpy);
  3270. CAMLlocal1(event);
  3271. alloc_XEvent(event);
  3272. GET_STATUS XNextEvent(
  3273. Display_val(dpy),
  3274. XEvent_val(event) );
  3275. CHECK_STATUS(XNextEvent, 0);
  3276. CAMLreturn(event);
  3277. }
  3278. CAMLprim value
  3279. ml_XMaskEvent( value dpy, value event_mask_list, value event )
  3280. {
  3281. long event_mask = Eventmask_val( event_mask_list );
  3282. GET_STATUS XMaskEvent(
  3283. Display_val(dpy),
  3284. event_mask,
  3285. XEvent_val(event) );
  3286. CHECK_STATUS(XMaskEvent, 0);
  3287. return Val_unit;
  3288. }
  3289. CAMLprim value
  3290. ml_XWindowEvent( value dpy, value win, value event_mask_list )
  3291. {
  3292. CAMLparam3( dpy, win, event_mask_list );
  3293. CAMLlocal1( event );
  3294. long event_mask = Eventmask_val( event_mask_list );
  3295. XEvent event_return;
  3296. GET_STATUS XWindowEvent(
  3297. Display_val(dpy),
  3298. Window_val(win),
  3299. event_mask,
  3300. &event_return );
  3301. CHECK_STATUS(XWindowEvent, 0);
  3302. copy_XEvent(event_return, event);
  3303. CAMLreturn( event );
  3304. }
  3305. CAMLprim value
  3306. ml_XPending( value dpy )
  3307. {
  3308. return Val_int(XPending(
  3309. Display_val(dpy) ));
  3310. }
  3311. static const int event_mode_table[] = {
  3312. AsyncPointer,
  3313. SyncPointer,
  3314. AsyncKeyboard,
  3315. SyncKeyboard,
  3316. ReplayPointer,
  3317. ReplayKeyboard,
  3318. AsyncBoth,
  3319. SyncBoth,
  3320. };
  3321. #define Event_mode_val(i) (event_mode_table[Long_val(i)])
  3322. CAMLprim value
  3323. ml_XAllowEvents( value dpy, value event_mode, value time )
  3324. {
  3325. //GET_STATUS
  3326. XAllowEvents(
  3327. Display_val(dpy),
  3328. Event_mode_val(event_mode),
  3329. Time_val(time)
  3330. );
  3331. //CHECK_STATUS(XAllowEvents,1);
  3332. return Val_unit;
  3333. }
  3334. CAMLprim value
  3335. ml_XPutBackEvent( value dpy, value event )
  3336. {
  3337. GET_STATUS XPutBackEvent(
  3338. Display_val(dpy),
  3339. XEvent_val(event) );
  3340. CHECK_STATUS(XPutBackEvent, 0);
  3341. return Val_unit;
  3342. }
  3343. static const int event_type_table[] = {
  3344. KeyPress,
  3345. KeyRelease,
  3346. ButtonPress,
  3347. ButtonRelease,
  3348. MotionNotify,
  3349. EnterNotify,
  3350. LeaveNotify,
  3351. FocusIn,
  3352. FocusOut,
  3353. KeymapNotify,
  3354. Expose,
  3355. GraphicsExpose,
  3356. NoExpose,
  3357. VisibilityNotify,
  3358. CreateNotify,
  3359. DestroyNotify,
  3360. UnmapNotify,
  3361. MapNotify,
  3362. MapRequest,
  3363. ReparentNotify,
  3364. ConfigureNotify,
  3365. ConfigureRequest,
  3366. GravityNotify,
  3367. ResizeRequest,
  3368. CirculateNotify,
  3369. CirculateRequest,
  3370. PropertyNotify,
  3371. SelectionClear,
  3372. SelectionRequest,
  3373. SelectionNotify,
  3374. ColormapNotify,
  3375. ClientMessage,
  3376. MappingNotify,
  3377. };
  3378. CAMLprim value
  3379. ml_XCheckTypedEvent( value dpy, value event_type, value event_return )
  3380. {
  3381. if (XCheckTypedEvent(
  3382. Display_val(dpy),
  3383. event_type_table[Long_val(event_type)],
  3384. XEvent_val(event_return) ))
  3385. return Val_true;
  3386. else
  3387. return Val_false;
  3388. }
  3389. static const int queued_mode_table[] = {
  3390. QueuedAlready,
  3391. QueuedAfterFlush,
  3392. QueuedAfterReading
  3393. };
  3394. CAMLprim value
  3395. ml_XEventsQueued( value dpy, value mode_i )
  3396. {
  3397. int mode = queued_mode_table[Long_val(mode_i)];
  3398. int n = XEventsQueued(
  3399. Display_val(dpy),
  3400. mode );
  3401. return Val_int(n);
  3402. }
  3403. static inline value Val_event_type(int type)
  3404. {
  3405. switch (type)
  3406. {
  3407. case KeyPress: return Val_int(0);
  3408. case KeyRelease: return Val_int(1);
  3409. case ButtonPress: return Val_int(2);
  3410. case ButtonRelease: return Val_int(3);
  3411. case MotionNotify: return Val_int(4);
  3412. case EnterNotify: return Val_int(5);
  3413. case LeaveNotify: return Val_int(6);
  3414. case FocusIn: return Val_int(7);
  3415. case FocusOut: return Val_int(8);
  3416. case KeymapNotify: return Val_int(9);
  3417. case Expose: return Val_int(10);
  3418. case GraphicsExpose: return Val_int(11);
  3419. case NoExpose: return Val_int(12);
  3420. case VisibilityNotify: return Val_int(13);
  3421. case CreateNotify: return Val_int(14);
  3422. case DestroyNotify: return Val_int(15);
  3423. case UnmapNotify: return Val_int(16);
  3424. case MapNotify: return Val_int(17);
  3425. case MapRequest: return Val_int(18);
  3426. case ReparentNotify: return Val_int(19);
  3427. case ConfigureNotify: return Val_int(20);
  3428. case ConfigureRequest: return Val_int(21);
  3429. case GravityNotify: return Val_int(22);
  3430. case ResizeRequest: return Val_int(23);
  3431. case CirculateNotify: return Val_int(24);
  3432. case CirculateRequest: return Val_int(25);
  3433. case PropertyNotify: return Val_int(26);
  3434. case SelectionClear: return Val_int(27);
  3435. case SelectionRequest: return Val_int(28);
  3436. case SelectionNotify: return Val_int(29);
  3437. case ColormapNotify: return Val_int(30);
  3438. case ClientMessage: return Val_int(31);
  3439. case MappingNotify: return Val_int(32);
  3440. default: caml_failwith("unhandled event type");
  3441. }
  3442. return Val_unit;
  3443. }
  3444. CAMLprim value
  3445. ml_XEvent_type( value event )
  3446. {
  3447. return Val_event_type(XEvent_val(event)->type);
  3448. }
  3449. /* {{{ Get XEvents datas */
  3450. CAMLprim value
  3451. ml_XAnyEvent_datas( value event )
  3452. {
  3453. CAMLparam1( event );
  3454. CAMLlocal1( dat );
  3455. XEvent * e = XEvent_val(event);
  3456. dat = caml_alloc(5, 0);
  3457. Store_field( dat, 0, Val_event_type(e->xany.type) );
  3458. Store_field( dat, 1, Val_ulong(e->xany.serial) );
  3459. Store_field( dat, 2, Val_bool(e->xany.send_event) );
  3460. Store_field( dat, 3, Val_Display(e->xany.display) );
  3461. Store_field( dat, 4, Val_Window(e->xany.window) );
  3462. CAMLreturn( dat );
  3463. }
  3464. #define CHECK_EVENT_TYPE 1
  3465. // with 64 bit integers there's no need to check Time overflow anymore
  3466. #define CHECK_TIME_OVERFLOW 0
  3467. static const unsigned int logical_state_mask_table[] = {
  3468. AnyModifier,
  3469. Button1Mask,
  3470. Button2Mask,
  3471. Button3Mask,
  3472. Button4Mask,
  3473. Button5Mask,
  3474. ShiftMask,
  3475. LockMask,
  3476. ControlMask,
  3477. Mod1Mask,
  3478. Mod2Mask,
  3479. Mod3Mask,
  3480. Mod4Mask,
  3481. Mod5Mask
  3482. };
  3483. //define State_mask_val(i) (logical_state_mask_table[Long_val(i)])
  3484. static unsigned int State_mask_val(li)
  3485. {
  3486. int c_mask = 0;
  3487. while ( li != Val_emptylist )
  3488. {
  3489. value head = Field(li, 0);
  3490. c_mask |= logical_state_mask_table[Long_val(head)];
  3491. li = Field(li, 1);
  3492. }
  3493. return c_mask;
  3494. }
  3495. #define Val_AnyModifier Val_int(0)
  3496. #define Val_Button1Mask Val_int(1)
  3497. #define Val_Button2Mask Val_int(2)
  3498. #define Val_Button3Mask Val_int(3)
  3499. #define Val_Button4Mask Val_int(4)
  3500. #define Val_Button5Mask Val_int(5)
  3501. #define Val_ShiftMask Val_int(6)
  3502. #define Val_LockMask Val_int(7)
  3503. #define Val_ControlMask Val_int(8)
  3504. #define Val_Mod1Mask Val_int(9)
  3505. #define Val_Mod2Mask Val_int(10)
  3506. #define Val_Mod3Mask Val_int(11)
  3507. #define Val_Mod4Mask Val_int(12)
  3508. #define Val_Mod5Mask Val_int(13)
  3509. static inline value Val_state_mask(unsigned int c_mask)
  3510. {
  3511. CAMLparam0();
  3512. CAMLlocal2(li, cons);
  3513. li = Val_emptylist;
  3514. #define push_mask(mask, Val_mask) \
  3515. if (c_mask & mask) { \
  3516. cons = caml_alloc(2, 0); \
  3517. Store_field(cons, 0, Val_mask); \
  3518. Store_field(cons, 1, li); \
  3519. li = cons; \
  3520. }
  3521. push_mask( AnyModifier, Val_AnyModifier )
  3522. push_mask( Button1Mask, Val_Button1Mask )
  3523. push_mask( Button2Mask, Val_Button2Mask )
  3524. push_mask( Button3Mask, Val_Button3Mask )
  3525. push_mask( Button4Mask, Val_Button4Mask )
  3526. push_mask( Button5Mask, Val_Button5Mask )
  3527. push_mask( ShiftMask, Val_ShiftMask )
  3528. push_mask( LockMask, Val_LockMask )
  3529. push_mask( ControlMask, Val_ControlMask )
  3530. push_mask( Mod1Mask, Val_Mod1Mask )
  3531. push_mask( Mod2Mask, Val_Mod2Mask )
  3532. push_mask( Mod3Mask, Val_Mod3Mask )
  3533. push_mask( Mod4Mask, Val_Mod4Mask )
  3534. push_mask( Mod5Mask, Val_Mod5Mask )
  3535. CAMLreturn(li);
  3536. }
  3537. /* KeyPress / KeyRelease */
  3538. CAMLprim value
  3539. ml_XKeyEvent_datas( value event )
  3540. {
  3541. CAMLparam1( event );
  3542. CAMLlocal1( dat );
  3543. XEvent * e;
  3544. e = XEvent_val(event);
  3545. #if CHECK_EVENT_TYPE
  3546. // The type inference should garanty this:
  3547. if (e->type != KeyPress &&
  3548. e->type != KeyRelease)
  3549. caml_invalid_argument("not a key event");
  3550. #endif
  3551. #if CHECK_TIME_OVERFLOW
  3552. if (e->xkey.time > MAX_INT64)
  3553. caml_failwith("xKeyEvent_datas: time value overflow");
  3554. #endif
  3555. dat = caml_alloc(14, 0);
  3556. Store_field( dat, 0, Val_ulong(e->xkey.serial) );
  3557. Store_field( dat, 1, Val_bool(e->xkey.send_event) );
  3558. Store_field( dat, 2, Val_Display(e->xkey.display) );
  3559. Store_field( dat, 3, Val_Window(e->xkey.window) );
  3560. Store_field( dat, 4, Val_Window(e->xkey.root) );
  3561. Store_field( dat, 5, Val_Window(e->xkey.subwindow) );
  3562. Store_field( dat, 6, Val_time(e->xkey.time) );
  3563. Store_field( dat, 7, Val_int(e->xkey.x) );
  3564. Store_field( dat, 8, Val_int(e->xkey.y) );
  3565. Store_field( dat, 9, Val_int(e->xkey.x_root) );
  3566. Store_field( dat, 10, Val_int(e->xkey.y_root) );
  3567. Store_field( dat, 11, Val_state_mask(e->xkey.state) );
  3568. Store_field( dat, 12, Val_KeyCode(e->xkey.keycode) );
  3569. Store_field( dat, 13, Val_bool(e->xkey.same_screen) );
  3570. CAMLreturn( dat );
  3571. }
  3572. #if 0
  3573. #define Val_Button1Mask Val_int(0)
  3574. #define Val_Button2Mask Val_int(1)
  3575. #define Val_Button3Mask Val_int(2)
  3576. #define Val_Button4Mask Val_int(3)
  3577. #define Val_Button5Mask Val_int(4)
  3578. static inline value
  3579. Val_button_mask( unsigned int state_mask )
  3580. {
  3581. CAMLparam0();
  3582. CAMLlocal2(li, cons);
  3583. li = Val_emptylist;
  3584. if (state_mask & Button1Mask) {
  3585. cons = caml_alloc(2, 0);
  3586. Store_field( cons, 0, Val_Button1Mask );
  3587. Store_field( cons, 1, li );
  3588. li = cons;
  3589. }
  3590. if (state_mask & Button2Mask) {
  3591. cons = caml_alloc(2, 0);
  3592. Store_field( cons, 0, Val_Button2Mask );
  3593. Store_field( cons, 1, li );
  3594. li = cons;
  3595. }
  3596. if (state_mask & Button3Mask) {
  3597. cons = caml_alloc(2, 0);
  3598. Store_field( cons, 0, Val_Button3Mask );
  3599. Store_field( cons, 1, li );
  3600. li = cons;
  3601. }
  3602. if (state_mask & Button4Mask) {
  3603. cons = caml_alloc(2, 0);
  3604. Store_field( cons, 0, Val_Button4Mask );
  3605. Store_field( cons, 1, li );
  3606. li = cons;
  3607. }
  3608. if (state_mask & Button5Mask) {
  3609. cons = caml_alloc(2, 0);
  3610. Store_field( cons, 0, Val_Button5Mask );
  3611. Store_field( cons, 1, li );
  3612. li = cons;
  3613. }
  3614. CAMLreturn(li);
  3615. }
  3616. #endif
  3617. /* MotionNotify */
  3618. CAMLprim value
  3619. ml_XMotionEvent_datas( value event )
  3620. {
  3621. CAMLparam1( event );
  3622. CAMLlocal1( dat );
  3623. XEvent * e;
  3624. e = XEvent_val(event);
  3625. #if CHECK_EVENT_TYPE
  3626. // The type inference should garanty this:
  3627. if (e->type != MotionNotify)
  3628. caml_invalid_argument("not a MotionNotify event");
  3629. #endif
  3630. #if CHECK_TIME_OVERFLOW
  3631. if (e->xmotion.time > MAX_INT64)
  3632. caml_failwith("xMotionEvent_datas: time value overflow");
  3633. #endif
  3634. dat = caml_alloc(14, 0);
  3635. Store_field( dat, 0, Val_ulong(e->xmotion.serial) );
  3636. Store_field( dat, 1, Val_bool(e->xmotion.send_event) );
  3637. Store_field( dat, 2, Val_Display(e->xmotion.display) );
  3638. Store_field( dat, 3, Val_Window(e->xmotion.window) );
  3639. Store_field( dat, 4, Val_Window(e->xmotion.root) );
  3640. Store_field( dat, 5, Val_Window(e->xmotion.subwindow) );
  3641. Store_field( dat, 6, Val_time(e->xmotion.time) );
  3642. Store_field( dat, 7, Val_int(e->xmotion.x) );
  3643. Store_field( dat, 8, Val_int(e->xmotion.y) );
  3644. Store_field( dat, 9, Val_int(e->xmotion.x_root) );
  3645. Store_field( dat, 10, Val_int(e->xmotion.y_root) );
  3646. Store_field( dat, 11, /*Val_button_mask*/Val_state_mask(e->xmotion.state) );
  3647. Store_field( dat, 12, Val_char(e->xmotion.is_hint) );
  3648. Store_field( dat, 13, Val_bool(e->xmotion.same_screen) );
  3649. CAMLreturn( dat );
  3650. }
  3651. static const unsigned int button_table[] = {
  3652. AnyButton,
  3653. Button1,
  3654. Button2,
  3655. Button3,
  3656. Button4,
  3657. Button5,
  3658. };
  3659. //unsigned int button = button_table[Long_val(v)];
  3660. #define Button_val(v) (button_table[Long_val(v)])
  3661. static inline value Val_button(unsigned int b)
  3662. {
  3663. switch (b) {
  3664. case AnyButton: return Val_int(0);
  3665. case Button1: return Val_int(1);
  3666. case Button2: return Val_int(2);
  3667. case Button3: return Val_int(3);
  3668. case Button4: return Val_int(4);
  3669. case Button5: return Val_int(5);
  3670. }
  3671. return Val_int(0);
  3672. }
  3673. /* ButtonPress / ButtonRelease */
  3674. CAMLprim value
  3675. ml_XButtonEvent_datas( value event )
  3676. {
  3677. CAMLparam1( event );
  3678. CAMLlocal1( dat );
  3679. XEvent * e;
  3680. e = XEvent_val(event);
  3681. #if CHECK_EVENT_TYPE
  3682. // The type inference should garanty this:
  3683. if (e->type != ButtonPress &&
  3684. e->type != ButtonRelease)
  3685. caml_invalid_argument("not a MotionNotify event");
  3686. #endif
  3687. #if CHECK_TIME_OVERFLOW
  3688. if (e->xmotion.time > MAX_INT64)
  3689. caml_failwith("xButtonEvent_datas: time value overflow");
  3690. #endif
  3691. dat = caml_alloc(14, 0);
  3692. Store_field( dat, 0, Val_ulong(e->xbutton.serial) );
  3693. Store_field( dat, 1, Val_bool(e->xbutton.send_event) );
  3694. Store_field( dat, 2, Val_Display(e->xbutton.display) );
  3695. Store_field( dat, 3, Val_Window(e->xbutton.window) );
  3696. Store_field( dat, 4, Val_Window(e->xbutton.root) );
  3697. Store_field( dat, 5, Val_Window(e->xbutton.subwindow) );
  3698. Store_field( dat, 6, Val_time(e->xbutton.time) );
  3699. Store_field( dat, 7, Val_int(e->xbutton.x) );
  3700. Store_field( dat, 8, Val_int(e->xbutton.y) );
  3701. Store_field( dat, 9, Val_int(e->xbutton.x_root) );
  3702. Store_field( dat, 10, Val_int(e->xbutton.y_root) );
  3703. Store_field( dat, 11, Val_uint(e->xbutton.state) );
  3704. Store_field( dat, 12, Val_button(e->xbutton.button) );
  3705. Store_field( dat, 13, Val_bool(e->xbutton.same_screen) );
  3706. CAMLreturn( dat );
  3707. }
  3708. static inline value Val_crossing_mode(int mode)
  3709. {
  3710. switch (mode) {
  3711. case NotifyNormal : return Val_int(0);
  3712. case NotifyGrab : return Val_int(1);
  3713. case NotifyUngrab : return Val_int(2);
  3714. }
  3715. return Val_int(0);
  3716. }
  3717. static inline value Val_crossing_detail(int detail)
  3718. {
  3719. switch (detail) {
  3720. case NotifyAncestor : return Val_int(0);
  3721. case NotifyVirtual : return Val_int(1);
  3722. case NotifyInferior : return Val_int(2);
  3723. case NotifyNonlinear : return Val_int(3);
  3724. case NotifyNonlinearVirtual : return Val_int(4);
  3725. }
  3726. return Val_int(0);
  3727. }
  3728. static inline value Val_crossing_state(int state)
  3729. {
  3730. switch (state) {
  3731. case Button1Mask : return Val_int(0);
  3732. case Button2Mask : return Val_int(1);
  3733. case Button3Mask : return Val_int(2);
  3734. case Button4Mask : return Val_int(3);
  3735. case Button5Mask : return Val_int(4);
  3736. case ShiftMask : return Val_int(5);
  3737. case LockMask : return Val_int(6);
  3738. case ControlMask : return Val_int(7);
  3739. case Mod1Mask : return Val_int(8);
  3740. case Mod2Mask : return Val_int(9);
  3741. case Mod3Mask : return Val_int(10);
  3742. case Mod4Mask : return Val_int(11);
  3743. case Mod5Mask : return Val_int(12);
  3744. }
  3745. return Val_int(0);
  3746. }
  3747. /* EnterNotify / LeaveNotify */
  3748. CAMLprim value
  3749. ml_XCrossingEvent_datas( value event )
  3750. {
  3751. CAMLparam1( event );
  3752. CAMLlocal1( dat );
  3753. XEvent * e;
  3754. e = XEvent_val(event);
  3755. #if CHECK_EVENT_TYPE
  3756. // The type inference should garanty this:
  3757. if (e->type != EnterNotify &&
  3758. e->type != LeaveNotify)
  3759. caml_invalid_argument("not a Crossing event");
  3760. #endif
  3761. #if CHECK_TIME_OVERFLOW
  3762. if (e->xcrossing.time > MAX_INT64)
  3763. caml_failwith("xCrossingEvent_datas: time value overflow");
  3764. #endif
  3765. dat = caml_alloc(13, 0);
  3766. Store_field( dat, 0, Val_Window(e->xcrossing.window) );
  3767. Store_field( dat, 1, Val_Window(e->xcrossing.root) );
  3768. Store_field( dat, 2, Val_Window(e->xcrossing.subwindow) );
  3769. Store_field( dat, 3, Val_time(e->xcrossing.time) );
  3770. Store_field( dat, 4, Val_int(e->xcrossing.x) );
  3771. Store_field( dat, 5, Val_int(e->xcrossing.y) );
  3772. Store_field( dat, 6, Val_int(e->xcrossing.x_root) );
  3773. Store_field( dat, 7, Val_int(e->xcrossing.y_root) );
  3774. Store_field( dat, 8, Val_crossing_mode(e->xcrossing.mode) );
  3775. Store_field( dat, 9, Val_crossing_detail(e->xcrossing.detail) );
  3776. Store_field( dat, 10, Val_bool(e->xcrossing.same_screen) );
  3777. Store_field( dat, 11, Val_bool(e->xcrossing.focus) );
  3778. Store_field( dat, 12, Val_crossing_state(e->xcrossing.state) );
  3779. CAMLreturn( dat );
  3780. }
  3781. static inline value Val_focus_mode(int n)
  3782. {
  3783. switch (n) {
  3784. case NotifyNormal : return Val_int(0);
  3785. case NotifyGrab : return Val_int(1);
  3786. case NotifyUngrab : return Val_int(2);
  3787. case NotifyWhileGrabbed: return Val_int(3);
  3788. }
  3789. return Val_int(0);
  3790. }
  3791. static inline value Val_focus_detail(int d)
  3792. {
  3793. switch (d) {
  3794. case NotifyAncestor : return Val_int(0);
  3795. case NotifyVirtual : return Val_int(1);
  3796. case NotifyInferior : return Val_int(2);
  3797. case NotifyNonlinear : return Val_int(3);
  3798. case NotifyNonlinearVirtual: return Val_int(4);
  3799. case NotifyPointer : return Val_int(5);
  3800. case NotifyPointerRoot : return Val_int(6);
  3801. case NotifyDetailNone : return Val_int(7);
  3802. }
  3803. return Val_int(0);
  3804. }
  3805. /* FocusIn / FocusOut */
  3806. CAMLprim value
  3807. ml_XFocusChangeEvent_datas( value event )
  3808. {
  3809. CAMLparam1( event );
  3810. CAMLlocal1( dat );
  3811. XEvent * e;
  3812. e = XEvent_val(event);
  3813. #if CHECK_EVENT_TYPE
  3814. // The type inference should garanty this:
  3815. if (e->type != FocusIn &&
  3816. e->type != FocusOut)
  3817. caml_invalid_argument("not a FocusChange event");
  3818. #endif
  3819. dat = caml_alloc(2, 0);
  3820. Store_field( dat, 0, Val_focus_mode(e->xfocus.mode) );
  3821. Store_field( dat, 1, Val_focus_detail(e->xfocus.detail) );
  3822. CAMLreturn( dat );
  3823. }
  3824. /* KeymapNotify */
  3825. CAMLprim value
  3826. ml_XKeymapEvent_datas( value event )
  3827. {
  3828. CAMLparam1( event );
  3829. CAMLlocal2( dat, key_str );
  3830. XEvent * e;
  3831. e = XEvent_val(event);
  3832. #if CHECK_EVENT_TYPE
  3833. // The type inference should garanty this:
  3834. if (e->type != KeymapNotify)
  3835. caml_invalid_argument("not a KeymapNotify event");
  3836. #endif
  3837. key_str = caml_alloc_string (32);
  3838. memcpy( String_val(key_str), (e->xkeymap.key_vector), 32 );
  3839. dat = caml_alloc(1, 0);
  3840. Store_field( dat, 0, key_str );
  3841. CAMLreturn( dat );
  3842. }
  3843. /* Expose */
  3844. CAMLprim value
  3845. ml_XExposeEvent_datas( value event )
  3846. {
  3847. CAMLparam1( event );
  3848. CAMLlocal1( dat );
  3849. XEvent * e;
  3850. e = XEvent_val(event);
  3851. #if CHECK_EVENT_TYPE
  3852. // The type inference should garanty this:
  3853. if (e->type != Expose)
  3854. caml_invalid_argument("not an Expose event");
  3855. #endif
  3856. dat = caml_alloc(5, 0);
  3857. Store_field( dat, 0, Val_int(e->xexpose.x) );
  3858. Store_field( dat, 1, Val_int(e->xexpose.y) );
  3859. Store_field( dat, 2, Val_int(e->xexpose.width) );
  3860. Store_field( dat, 3, Val_int(e->xexpose.height) );
  3861. Store_field( dat, 4, Val_int(e->xexpose.count) );
  3862. CAMLreturn( dat );
  3863. }
  3864. /*
  3865. TODO GraphicsExpose
  3866. TODO NoExpose
  3867. */
  3868. static inline value Val_visibility_state(int v)
  3869. {
  3870. switch (v) {
  3871. case VisibilityUnobscured : return Val_int(0);
  3872. case VisibilityPartiallyObscured: return Val_int(1);
  3873. case VisibilityFullyObscured : return Val_int(2);
  3874. }
  3875. return Val_int(0);
  3876. }
  3877. /* VisibilityNotify */
  3878. CAMLprim value
  3879. ml_XVisibilityEvent_datas( value event )
  3880. {
  3881. CAMLparam1( event );
  3882. CAMLlocal1( dat );
  3883. XEvent * e;
  3884. e = XEvent_val(event);
  3885. #if CHECK_EVENT_TYPE
  3886. // The type inference should garanty this:
  3887. if (e->type != VisibilityNotify)
  3888. caml_invalid_argument("not a VisibilityNotify event");
  3889. #endif
  3890. dat = caml_alloc(1, 0);
  3891. Store_field( dat, 0, Val_visibility_state(e->xvisibility.state) );
  3892. CAMLreturn( dat );
  3893. }
  3894. /*
  3895. TODO CreateNotify
  3896. */
  3897. /* DestroyNotify */
  3898. CAMLprim value
  3899. ml_XDestroyWindowEvent_datas( value event )
  3900. {
  3901. CAMLparam1( event );
  3902. CAMLlocal1( dat );
  3903. XEvent * e;
  3904. e = XEvent_val(event);
  3905. #if CHECK_EVENT_TYPE
  3906. // The type inference should garanty this:
  3907. if (e->type != DestroyNotify)
  3908. caml_invalid_argument("not a DestroyNotify event");
  3909. #endif
  3910. dat = caml_alloc(2, 0);
  3911. Store_field( dat, 0, Val_Window(e->xdestroywindow.event) );
  3912. Store_field( dat, 1, Val_Window(e->xdestroywindow.window) );
  3913. CAMLreturn( dat );
  3914. }
  3915. /*
  3916. TODO UnmapNotify
  3917. TODO MapNotify
  3918. TODO MapRequest
  3919. */
  3920. /* ReparentNotify */
  3921. CAMLprim value
  3922. ml_XReparentEvent_datas( value event )
  3923. {
  3924. CAMLparam1( event );
  3925. CAMLlocal1( dat );
  3926. XEvent * e;
  3927. e = XEvent_val(event);
  3928. #if CHECK_EVENT_TYPE
  3929. // The type inference should garanty this:
  3930. if (e->type != ReparentNotify)
  3931. caml_invalid_argument("not a ReparentNotify event");
  3932. #endif
  3933. dat = caml_alloc(2, 0);
  3934. Store_field( dat, 0, Val_Window(e->xreparent.event) );
  3935. Store_field( dat, 1, Val_Window(e->xreparent.window) );
  3936. Store_field( dat, 2, Val_Window(e->xreparent.parent) );
  3937. Store_field( dat, 3, Val_int(e->xreparent.x) );
  3938. Store_field( dat, 4, Val_int(e->xreparent.y) );
  3939. Store_field( dat, 5, Val_bool(e->xreparent.override_redirect) );
  3940. CAMLreturn( dat );
  3941. }
  3942. /* ConfigureNotify */
  3943. CAMLprim value
  3944. ml_XConfigureEvent_datas( value event )
  3945. {
  3946. CAMLparam1( event );
  3947. CAMLlocal1( dat );
  3948. XEvent * e;
  3949. e = XEvent_val(event);
  3950. #if CHECK_EVENT_TYPE
  3951. // The type inference should garanty this:
  3952. if (e->type != ConfigureNotify)
  3953. caml_invalid_argument("not a ConfigureNotify event");
  3954. #endif
  3955. dat = caml_alloc(7, 0);
  3956. Store_field( dat, 0, Val_int(e->xconfigure.x) );
  3957. Store_field( dat, 1, Val_int(e->xconfigure.y) );
  3958. Store_field( dat, 2, Val_int(e->xconfigure.width) );
  3959. Store_field( dat, 3, Val_int(e->xconfigure.height) );
  3960. Store_field( dat, 4, Val_int(e->xconfigure.border_width) );
  3961. Store_field( dat, 5, Val_Window(e->xconfigure.above) );
  3962. Store_field( dat, 6, Val_bool(e->xconfigure.override_redirect) );
  3963. CAMLreturn( dat );
  3964. }
  3965. /* ConfigureRequest */
  3966. static inline value Val_xconfreq_detail(int detail)
  3967. {
  3968. switch (detail) {
  3969. case Above : return Val_int(0);
  3970. case Below : return Val_int(1);
  3971. case TopIf : return Val_int(2);
  3972. case BottomIf : return Val_int(3);
  3973. case Opposite : return Val_int(4);
  3974. }
  3975. return Val_int(0);
  3976. }
  3977. CAMLprim value
  3978. ml_XConfigureRequestEvent_datas( value event )
  3979. {
  3980. CAMLparam1( event );
  3981. CAMLlocal1( dat );
  3982. XEvent * e;
  3983. e = XEvent_val(event);
  3984. #if CHECK_EVENT_TYPE
  3985. // The type inference should garanty this:
  3986. if (e->type != ConfigureRequest)
  3987. caml_invalid_argument("not a ConfigureRequest event");
  3988. #endif
  3989. dat = caml_alloc(7, 0);
  3990. Store_field( dat, 0, Val_Window(e->xconfigurerequest.parent) );
  3991. Store_field( dat, 1, Val_Window(e->xconfigurerequest.window) );
  3992. Store_field( dat, 2, Val_int(e->xconfigurerequest.x) );
  3993. Store_field( dat, 3, Val_int(e->xconfigurerequest.y) );
  3994. Store_field( dat, 4, Val_int(e->xconfigurerequest.width) );
  3995. Store_field( dat, 5, Val_int(e->xconfigurerequest.height) );
  3996. Store_field( dat, 6, Val_int(e->xconfigurerequest.border_width) );
  3997. Store_field( dat, 7, Val_Window(e->xconfigurerequest.above) );
  3998. Store_field( dat, 8, Val_xconfreq_detail(e->xconfigurerequest.detail) );
  3999. Store_field( dat, 9, Val_ulong(e->xconfigurerequest.value_mask) ); /* TODO */
  4000. CAMLreturn( dat );
  4001. }
  4002. /*
  4003. TODO GravityNotify
  4004. */
  4005. /* ResizeRequest */
  4006. CAMLprim value
  4007. ml_XResizeRequestEvent_datas( value event )
  4008. {
  4009. CAMLparam1( event );
  4010. CAMLlocal1( dat );
  4011. XEvent * e;
  4012. e = XEvent_val(event);
  4013. #if CHECK_EVENT_TYPE
  4014. // The type inference should garanty this:
  4015. if (e->type != ResizeRequest)
  4016. caml_invalid_argument("not a ResizeRequest event");
  4017. #endif
  4018. dat = caml_alloc(2, 0);
  4019. Store_field( dat, 0, Val_int(e->xresizerequest.width) );
  4020. Store_field( dat, 1, Val_int(e->xresizerequest.height) );
  4021. CAMLreturn( dat );
  4022. }
  4023. /*
  4024. TODO CirculateNotify
  4025. TODO CirculateRequest
  4026. TODO PropertyNotify
  4027. TODO SelectionClear
  4028. TODO SelectionRequest
  4029. */
  4030. CAMLprim value
  4031. Val_Atom_option( Atom a )
  4032. {
  4033. if (a == None) return Val_none;
  4034. else return Val_some( Val_Atom(a) );
  4035. }
  4036. /* SelectionNotify */
  4037. CAMLprim value
  4038. ml_XSelectionEvent_datas( value event )
  4039. {
  4040. CAMLparam1( event );
  4041. CAMLlocal1( dat );
  4042. XEvent * e;
  4043. e = XEvent_val(event);
  4044. #if CHECK_EVENT_TYPE
  4045. // The type inference should garanty this:
  4046. if (e->type != SelectionNotify)
  4047. caml_invalid_argument("not a SelectionNotify event");
  4048. #endif
  4049. #if CHECK_TIME_OVERFLOW
  4050. if (e->xselection.time > MAX_INT64)
  4051. caml_failwith("xSelectionEvent_datas: time value overflow");
  4052. #endif
  4053. dat = caml_alloc(5, 0);
  4054. Store_field( dat, 0, Val_Window(e->xselection.requestor) );
  4055. Store_field( dat, 1, Val_Atom(e->xselection.selection) );
  4056. Store_field( dat, 2, Val_Atom(e->xselection.target) );
  4057. Store_field( dat, 3, Val_Atom_option(e->xselection.property) ); /* Atom or None */
  4058. Store_field( dat, 4, Val_time(e->xselection.time) );
  4059. CAMLreturn( dat );
  4060. }
  4061. /*
  4062. TODO ColormapNotify
  4063. TODO ClientMessage
  4064. TODO MappingNotify
  4065. */
  4066. /* XErrorEvent */
  4067. CAMLprim value
  4068. ml_XErrorEvent_datas( value event )
  4069. {
  4070. CAMLparam1( event );
  4071. CAMLlocal1( dat );
  4072. XEvent * e;
  4073. e = XEvent_val(event);
  4074. #if CHECK_EVENT_TYPE
  4075. /*
  4076. // don't know how is set this field for the XerrorEvent
  4077. if (e->type != ??? )
  4078. caml_invalid_argument("not an error event");
  4079. */
  4080. #endif
  4081. #if CHECK_TIME_OVERFLOW
  4082. if (e->xkey.time > MAX_INT64)
  4083. caml_failwith("xKeyEvent_datas: time value overflow");
  4084. #endif
  4085. dat = caml_alloc(6, 0);
  4086. Store_field( dat, 0, Val_Display(e->xerror.display) );
  4087. Store_field( dat, 1, Val_XID(e->xerror.resourceid ) );
  4088. Store_field( dat, 2, Val_ulong(e->xerror.serial ) );
  4089. Store_field( dat, 3, Val_char(e->xerror.error_code ) );
  4090. Store_field( dat, 4, Val_char(e->xerror.request_code ) );
  4091. Store_field( dat, 5, Val_char(e->xerror.minor_code ) );
  4092. CAMLreturn( dat );
  4093. }
  4094. /* }}} */
  4095. CAMLprim value
  4096. ml_XSendEvent(
  4097. value dpy,
  4098. value win,
  4099. value propagate,
  4100. value event_mask,
  4101. value event_content )
  4102. {
  4103. XEvent *ev;
  4104. ev = malloc(sizeof(XEvent));
  4105. value cont = Field(event_content,0);
  4106. switch (Tag_val(event_content))
  4107. {
  4108. case 0: // {{{ XMotionEvCnt
  4109. ev->type = MotionNotify;
  4110. ev->xmotion.serial = ULong_val(Field(cont, 0));
  4111. ev->xmotion.send_event = Bool_val(Field(cont, 1));
  4112. ev->xmotion.display = Display_val(Field(cont, 2));
  4113. ev->xmotion.window = Window_val(Field(cont, 3));
  4114. ev->xmotion.root = Window_val(Field(cont, 4));
  4115. ev->xmotion.subwindow = Window_val(Field(cont, 5));
  4116. ev->xmotion.time = Time_val(Field(cont, 6));
  4117. ev->xmotion.x = Int_val(Field(cont, 7));
  4118. ev->xmotion.y = Int_val(Field(cont, 8));
  4119. ev->xmotion.x_root = Int_val(Field(cont, 9));
  4120. ev->xmotion.y_root = Int_val(Field(cont, 10));
  4121. ev->xmotion.state = State_mask_val(Field(cont, 11));
  4122. ev->xmotion.is_hint = Char_val(Field(cont, 12));
  4123. ev->xmotion.same_screen = Bool_val(Field(cont, 13));
  4124. break; // }}}
  4125. case 1: // {{{ XKeyPressedEvCnt
  4126. ev->type = KeyPress;
  4127. ev->xkey.serial = ULong_val(Field(cont, 0));
  4128. ev->xkey.send_event = Bool_val(Field(cont, 1));
  4129. ev->xkey.display = Display_val(Field(cont, 2));
  4130. ev->xkey.window = Window_val(Field(cont, 3));
  4131. ev->xkey.root = Window_val(Field(cont, 4));
  4132. ev->xkey.subwindow = Window_val(Field(cont, 5));
  4133. ev->xkey.time = Time_val(Field(cont, 6));
  4134. ev->xkey.x = Int_val(Field(cont, 7));
  4135. ev->xkey.y = Int_val(Field(cont, 8));
  4136. ev->xkey.x_root = Int_val(Field(cont, 9));
  4137. ev->xkey.y_root = Int_val(Field(cont, 10));
  4138. ev->xkey.state = State_mask_val(Field(cont, 11));
  4139. ev->xkey.keycode = KeyCode_val(Field(cont, 12));
  4140. ev->xkey.same_screen = Bool_val(Field(cont, 13));
  4141. break; // }}}
  4142. case 2: // {{{ XKeyReleasedEvCnt
  4143. ev->type = KeyRelease;
  4144. ev->xkey.serial = ULong_val(Field(cont, 0));
  4145. ev->xkey.send_event = Bool_val(Field(cont, 1));
  4146. ev->xkey.display = Display_val(Field(cont, 2));
  4147. ev->xkey.window = Window_val(Field(cont, 3));
  4148. ev->xkey.root = Window_val(Field(cont, 4));
  4149. ev->xkey.subwindow = Window_val(Field(cont, 5));
  4150. ev->xkey.time = Time_val(Field(cont, 6));
  4151. ev->xkey.x = Int_val(Field(cont, 7));
  4152. ev->xkey.y = Int_val(Field(cont, 8));
  4153. ev->xkey.x_root = Int_val(Field(cont, 9));
  4154. ev->xkey.y_root = Int_val(Field(cont, 10));
  4155. ev->xkey.state = State_mask_val(Field(cont, 11));
  4156. ev->xkey.keycode = KeyCode_val(Field(cont, 12));
  4157. ev->xkey.same_screen = Bool_val(Field(cont, 13));
  4158. break; // }}}
  4159. case 3: // {{{ XButtonPressedEvCnt
  4160. ev->type = ButtonPress;
  4161. ev->xbutton.serial = ULong_val(Field(cont, 0));
  4162. ev->xbutton.send_event = Bool_val(Field(cont, 1));
  4163. ev->xbutton.display = Display_val(Field(cont, 2));
  4164. ev->xbutton.window = Window_val(Field(cont, 3));
  4165. ev->xbutton.root = Window_val(Field(cont, 4));
  4166. ev->xbutton.subwindow = Window_val(Field(cont, 5));
  4167. ev->xbutton.time = Time_val(Field(cont, 6));
  4168. ev->xbutton.x = Int_val(Field(cont, 7));
  4169. ev->xbutton.y = Int_val(Field(cont, 8));
  4170. ev->xbutton.x_root = Int_val(Field(cont, 9));
  4171. ev->xbutton.y_root = Int_val(Field(cont, 10));
  4172. ev->xbutton.state = UInt_val(Field(cont, 11));
  4173. ev->xbutton.button = Button_val(Field(cont, 12));
  4174. ev->xbutton.same_screen = Bool_val(Field(cont, 13));
  4175. break; // }}}
  4176. case 4: // {{{ XButtonReleasedEvCnt
  4177. ev->type = ButtonRelease;
  4178. ev->xbutton.serial = ULong_val(Field(cont, 0));
  4179. ev->xbutton.send_event = Bool_val(Field(cont, 1));
  4180. ev->xbutton.display = Display_val(Field(cont, 2));
  4181. ev->xbutton.window = Window_val(Field(cont, 3));
  4182. ev->xbutton.root = Window_val(Field(cont, 4));
  4183. ev->xbutton.subwindow = Window_val(Field(cont, 5));
  4184. ev->xbutton.time = Time_val(Field(cont, 6));
  4185. ev->xbutton.x = Int_val(Field(cont, 7));
  4186. ev->xbutton.y = Int_val(Field(cont, 8));
  4187. ev->xbutton.x_root = Int_val(Field(cont, 9));
  4188. ev->xbutton.y_root = Int_val(Field(cont, 10));
  4189. ev->xbutton.state = UInt_val(Field(cont, 11));
  4190. ev->xbutton.button = Button_val(Field(cont, 12));
  4191. ev->xbutton.same_screen = Bool_val(Field(cont, 13));
  4192. break; // }}}
  4193. case 5: // XCrossingEvCnt
  4194. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4195. break;
  4196. case 6: // XFocusChangeEvCnt
  4197. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4198. break;
  4199. case 7: // XKeymapEvCnt
  4200. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4201. break;
  4202. case 8: // XExposeEvCnt
  4203. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4204. break;
  4205. case 9: // XGraphicsExposeEvCnt
  4206. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4207. break;
  4208. case 10: // XNoExposeEvCnt
  4209. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4210. break;
  4211. case 11: // XVisibilityEvCnt
  4212. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4213. break;
  4214. case 12: // XCreateWindowEvCnt
  4215. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4216. break;
  4217. case 13: // XDestroyWindowEvCnt
  4218. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4219. break;
  4220. case 14: // XUnmapEvCnt
  4221. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4222. break;
  4223. case 15: // XMapEvCnt
  4224. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4225. break;
  4226. case 16: // XMapRequestEvCnt
  4227. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4228. break;
  4229. case 17: // XReparentEvCnt
  4230. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4231. break;
  4232. case 18: // XConfigureEvCnt
  4233. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4234. break;
  4235. case 19: // XConfigureRequestEvCnt
  4236. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4237. break;
  4238. case 20: // XGravityEvCnt
  4239. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4240. break;
  4241. case 21: // XResizeRequestEvCnt
  4242. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4243. break;
  4244. case 22: // XCirculateEvCnt
  4245. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4246. break;
  4247. case 23: // XCirculateRequestEvCnt
  4248. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4249. break;
  4250. case 24: // XPropertyEvCnt
  4251. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4252. break;
  4253. case 25: // XSelectionClearEvCnt
  4254. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4255. break;
  4256. case 26: // XSelectionRequestEvCnt
  4257. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4258. break;
  4259. case 27: // XSelectionEvCnt
  4260. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4261. break;
  4262. case 28: // XColormapEvCnt
  4263. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4264. break;
  4265. case 29: // XClientMessageEvCnt
  4266. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4267. break;
  4268. case 30: // XMappingEvCnt
  4269. caml_failwith("xSendEvent TODO: this event_content is not handled yet");
  4270. break;
  4271. default: caml_failwith("variant handling bug");
  4272. }
  4273. Status st = XSendEvent(
  4274. Display_val(dpy),
  4275. Window_val(win),
  4276. Bool_val(propagate),
  4277. event_mask_table[Long_val(event_mask)],
  4278. ev
  4279. );
  4280. free(ev);
  4281. if (st == 0) {
  4282. caml_failwith("xSendEvent: failed");
  4283. }
  4284. return Val_unit;
  4285. }
  4286. CAMLprim value
  4287. ml_XEvent_xclient_data_l_0( value event )
  4288. {
  4289. XEvent * e;
  4290. e = XEvent_val(event);
  4291. #if CHECK_EVENT_TYPE
  4292. // The type inference should garanty this:
  4293. if (e->type != ClientMessage)
  4294. caml_invalid_argument("not a ClientMessage event");
  4295. #endif
  4296. long atom = e->xclient.data.l[0];
  4297. return Val_Atom( atom );
  4298. }
  4299. /*
  4300. int XLookupString(
  4301. XKeyEvent* event_struct,
  4302. char* buffer_return,
  4303. int bytes_buffer,
  4304. KeySym* keysym_return,
  4305. XComposeStatus* status_in_out );
  4306. */
  4307. #if 0
  4308. #include <X11/keysym.h>
  4309. CAMLprim value
  4310. _ml_XLookupString( value event )
  4311. {
  4312. XEvent * e;
  4313. KeySym keysym;
  4314. e = XEvent_val(event);
  4315. XComposeStatus* status_in_out = NULL;
  4316. char buffer_txt[256];
  4317. char * p;
  4318. int nchar;
  4319. nchar = XLookupString(
  4320. &(e->xkey),
  4321. buffer_txt, sizeof(buffer_txt),
  4322. &keysym,
  4323. status_in_out );
  4324. for (p = buffer_txt; nchar > 0; ++p, --nchar)
  4325. printf("%c", *p);
  4326. printf("\n"); fflush(stdout);
  4327. switch (keysym) {
  4328. #define KEY_CASE(k) case k: printf(#k "\n"); break;
  4329. // {{{
  4330. KEY_CASE(XK_KP_F1)
  4331. KEY_CASE(XK_F1)
  4332. KEY_CASE(XK_a)
  4333. KEY_CASE(XK_b)
  4334. KEY_CASE(XK_c)
  4335. KEY_CASE(XK_d)
  4336. KEY_CASE(XK_e)
  4337. KEY_CASE(XK_f)
  4338. KEY_CASE(XK_g)
  4339. KEY_CASE(XK_h)
  4340. KEY_CASE(XK_i)
  4341. KEY_CASE(XK_j)
  4342. KEY_CASE(XK_A)
  4343. KEY_CASE(XK_B)
  4344. KEY_CASE(XK_C)
  4345. KEY_CASE(XK_D)
  4346. KEY_CASE(XK_E)
  4347. KEY_CASE(XK_F)
  4348. KEY_CASE(XK_G)
  4349. // }}}
  4350. #undef KEY_CASE
  4351. }
  4352. return Val_unit;
  4353. }
  4354. #endif
  4355. CAMLprim value
  4356. ml_XLookupString( value event, value buffer )
  4357. {
  4358. CAMLparam1( event );
  4359. CAMLlocal1( ret );
  4360. KeySym keysym;
  4361. XEvent * e = XEvent_val(event);
  4362. #if CHECK_EVENT_TYPE
  4363. if (e->type != KeyPress &&
  4364. e->type != KeyRelease)
  4365. caml_invalid_argument("not a key event");
  4366. #endif
  4367. // XComposeStatus stat;
  4368. int nchars = XLookupString( // from <X11/Xutil.h>
  4369. &(e->xkey),
  4370. String_val(buffer),
  4371. caml_string_length(buffer),
  4372. &keysym,
  4373. NULL /* &stat */ );
  4374. ret = caml_alloc(2, 0);
  4375. Store_field( ret, 0, Val_int(nchars) );
  4376. Store_field( ret, 1, Val_keysym(keysym) );
  4377. CAMLreturn( ret );
  4378. }
  4379. // TODO: Xutf8LookupString, XwcLookupString, XmbLookupString
  4380. CAMLprim value
  4381. ml_XLookupKeysym( value event, value index )
  4382. {
  4383. XEvent * e = XEvent_val(event);
  4384. #if CHECK_EVENT_TYPE
  4385. if (e->type != KeyPress &&
  4386. e->type != KeyRelease)
  4387. caml_invalid_argument("not a key event");
  4388. #endif
  4389. KeySym keysym = XLookupKeysym(
  4390. &(e->xkey),
  4391. Int_val(index) ); // index from 0 to (keysyms_per_keycode - 1)
  4392. return Val_keysym(keysym);
  4393. }
  4394. CAMLprim value
  4395. ml_XKeycodeToKeysym( value dpy, value keycode, value index )
  4396. {
  4397. KeySym keysym = XKeycodeToKeysym(
  4398. Display_val(dpy),
  4399. KeyCode_val(keycode),
  4400. Int_val(index) );
  4401. return Val_keysym(keysym);
  4402. }
  4403. CAMLprim value
  4404. ml_XRefreshKeyboardMapping( value event )
  4405. {
  4406. XEvent *e;
  4407. e = XEvent_val(event);
  4408. #if CHECK_EVENT_TYPE
  4409. if (e->type != MappingNotify)
  4410. caml_invalid_argument("not a MappingNotify event");
  4411. #endif
  4412. XRefreshKeyboardMapping(&(e->xmapping));
  4413. return Val_unit;
  4414. }
  4415. CAMLprim value
  4416. ml_XDisplayKeycodes( value dpy )
  4417. {
  4418. CAMLlocal1( tpl );
  4419. int min_keycodes, max_keycodes;
  4420. //GET_STATUS
  4421. XDisplayKeycodes(
  4422. Display_val(dpy),
  4423. &min_keycodes,
  4424. &max_keycodes
  4425. );
  4426. //CHECK_STATUS(XDisplayKeycodes,1);
  4427. tpl = caml_alloc(2, 0);
  4428. Store_field( tpl, 0, Val_KeyCode(min_keycodes) );
  4429. Store_field( tpl, 1, Val_KeyCode(max_keycodes) );
  4430. return tpl;
  4431. }
  4432. /*
  4433. TODO:
  4434. //GET_STATUS
  4435. XRebindKeysym(
  4436. Display_val(dpy),
  4437. KeySym keysym,
  4438. KeySym* list,
  4439. int mod_count,
  4440. _Xconst unsigned char* string,
  4441. int bytes_string
  4442. );
  4443. //CHECK_STATUS(XRebindKeysym,0);
  4444. http://tronche.com/gui/x/xlib/utilities/XRebindKeysym.html
  4445. */
  4446. CAMLprim value
  4447. ml_XGetKeyboardMapping( value dpy, value first_keycode, value ml_keycode_count )
  4448. {
  4449. CAMLparam3(dpy, first_keycode, ml_keycode_count);
  4450. CAMLlocal2(ml_keysyms, sub);
  4451. int keysyms_per_keycode;
  4452. KeySym *keysyms;
  4453. unsigned int keysyms_len;
  4454. int i, j;
  4455. int keycode_count = Int_val(ml_keycode_count);
  4456. {
  4457. int min_keycode, max_keycode;
  4458. XDisplayKeycodes(
  4459. Display_val(dpy),
  4460. &min_keycode,
  4461. &max_keycode
  4462. );
  4463. if (Long_val(first_keycode) < min_keycode)
  4464. caml_invalid_argument("xGetKeyboardMapping: "
  4465. "first_keycode must be greater than or equal to min_keycode");
  4466. }
  4467. keysyms = XGetKeyboardMapping(
  4468. Display_val(dpy),
  4469. KeyCode_val(first_keycode),
  4470. keycode_count,
  4471. &keysyms_per_keycode
  4472. );
  4473. // number of elements in the KeySyms list
  4474. keysyms_len = (keycode_count * keysyms_per_keycode);
  4475. ml_keysyms = caml_alloc(keycode_count, 0);
  4476. printf("keysyms_per_keycode = %d\n", keysyms_per_keycode); // XXX DEBUG XXX
  4477. for (i=0; i < keycode_count; ++i)
  4478. {
  4479. int n = 0;
  4480. for (j=0; j < keysyms_per_keycode; ++j)
  4481. {
  4482. // don't return undefined keysyms
  4483. if (keysyms[keysyms_per_keycode + i + j] != NoSymbol) n++;
  4484. }
  4485. sub = caml_alloc(n, 0);
  4486. for (j=0; j < n; ++j)
  4487. {
  4488. Store_field(sub, j,
  4489. Val_keysym( keysyms[keysyms_per_keycode + i + j] )
  4490. );
  4491. }
  4492. Store_field(ml_keysyms, i, sub);
  4493. }
  4494. XFree(keysyms);
  4495. CAMLreturn( ml_keysyms );
  4496. }
  4497. // http://tronche.com/gui/x/xlib/input/XGetKeyboardMapping.html
  4498. /*
  4499. TODO:
  4500. KeySym keysym = XStringToKeysym( char* string );
  4501. */
  4502. CAMLprim value
  4503. ml_XChangeKeyboardMapping( // ---------------- WIP
  4504. value dpy,
  4505. value first_keycode,
  4506. value keysyms_per_keycode,
  4507. value keysyms_arr,
  4508. value num_codes )
  4509. {
  4510. KeySym* keysyms;
  4511. int i, keysyms_len;
  4512. int keysyms_len_should;
  4513. keysyms_len = Wosize_val(keysyms_arr);
  4514. keysyms_len_should = Int_val(num_codes) * Int_val(keysyms_per_keycode);
  4515. if (keysyms_len != keysyms_len_should) {
  4516. caml_invalid_argument("xChangeKeyboardMapping: "
  4517. "keysyms array should contain "
  4518. "(num_codes * keysyms_per_keycode) elements");
  4519. }
  4520. /* From the man: http://tronche.com/gui/x/xlib/input/XChangeKeyboardMapping.html
  4521. The specified first_keycode must be greater than or equal to min_keycode
  4522. returned by XDisplayKeycodes(), or a BadValue error results.
  4523. In addition, the following expression must be less than or equal to max_keycode,
  4524. or a BadValue error results: (first_keycode + num_codes - 1)
  4525. TODO: handle this BadValue error */
  4526. {
  4527. int min_keycode, max_keycode;
  4528. XDisplayKeycodes(
  4529. Display_val(dpy),
  4530. &min_keycode,
  4531. &max_keycode
  4532. );
  4533. if (Long_val(first_keycode) < min_keycode) {
  4534. caml_invalid_argument("xChangeKeyboardMapping: "
  4535. "first_keycode must be greater than or equal to min_keycode");
  4536. }
  4537. if ((Long_val(first_keycode) + Int_val(num_codes) - 1) > max_keycode) {
  4538. caml_invalid_argument("xChangeKeyboardMapping: "
  4539. "(first_keycode + num_codes - 1) must be less than or equal to max_keycode");
  4540. }
  4541. }
  4542. keysyms = malloc(keysyms_len * sizeof(KeySym));
  4543. for (i=0; i < keysyms_len; ++i)
  4544. {
  4545. keysyms[i] = Keysym_val(Field(keysyms_arr, i));
  4546. }
  4547. //GET_STATUS
  4548. XChangeKeyboardMapping(
  4549. Display_val(dpy),
  4550. KeyCode_val(first_keycode),
  4551. Int_val(keysyms_per_keycode),
  4552. keysyms,
  4553. Int_val(num_codes)
  4554. );
  4555. free(keysyms);
  4556. //CHECK_STATUS(XChangeKeyboardMapping,0);
  4557. return Val_unit;
  4558. }
  4559. CAMLprim value
  4560. ml_XChangeKeyboardMapping_single(
  4561. value dpy,
  4562. value first_keycode,
  4563. value keysym )
  4564. {
  4565. KeySym keysyms[1];
  4566. keysyms[0] = Keysym_val(keysym);
  4567. //GET_STATUS
  4568. XChangeKeyboardMapping(
  4569. Display_val(dpy),
  4570. KeyCode_val(first_keycode),
  4571. 1, keysyms, 1
  4572. );
  4573. //CHECK_STATUS(XChangeKeyboardMapping,0);
  4574. return Val_unit;
  4575. }
  4576. /* Keyboard */
  4577. CAMLprim value
  4578. ml_XAutoRepeatOff( value dpy )
  4579. {
  4580. GET_STATUS XAutoRepeatOff( Display_val(dpy) );
  4581. CHECK_STATUS(XAutoRepeatOff,1);
  4582. return Val_unit;
  4583. }
  4584. CAMLprim value
  4585. ml_XAutoRepeatOn( value dpy )
  4586. {
  4587. GET_STATUS XAutoRepeatOn( Display_val(dpy) );
  4588. CHECK_STATUS(XAutoRepeatOn,1);
  4589. return Val_unit;
  4590. }
  4591. CAMLprim value
  4592. ml_XQueryKeymap( value dpy )
  4593. {
  4594. CAMLparam1( dpy );
  4595. CAMLlocal1( ml_keys );
  4596. ml_keys = caml_alloc_string(32);
  4597. char *keys_ptr;
  4598. keys_ptr = String_val(ml_keys);
  4599. GET_STATUS XQueryKeymap(
  4600. Display_val(dpy),
  4601. keys_ptr );
  4602. CHECK_STATUS(XQueryKeymap,1);
  4603. CAMLreturn( ml_keys );
  4604. }
  4605. CAMLprim value
  4606. ml_XQueryPointer( value dpy, value win )
  4607. {
  4608. CAMLparam2( dpy, win );
  4609. CAMLlocal2( pntr, subp );
  4610. Window root, child;
  4611. int root_x, root_y, win_x, win_y;
  4612. unsigned int mask;
  4613. Bool b = XQueryPointer(
  4614. Display_val(dpy),
  4615. Window_val(win),
  4616. &root,
  4617. &child,
  4618. &root_x,
  4619. &root_y,
  4620. &win_x,
  4621. &win_y,
  4622. &mask
  4623. );
  4624. pntr = caml_alloc(5, 0);
  4625. if (b) {
  4626. subp = caml_alloc(3, 0);
  4627. Store_field( subp, 0, Val_Window(child) );
  4628. Store_field( subp, 1, Val_int(win_x) );
  4629. Store_field( subp, 2, Val_int(win_y) );
  4630. Store_field( pntr, 0, Val_Window(root) );
  4631. Store_field( pntr, 1, Val_int(root_x) );
  4632. Store_field( pntr, 2, Val_int(root_y) );
  4633. Store_field( pntr, 3, Val_some( subp ) );
  4634. Store_field( pntr, 4, Val_state_mask(mask) );
  4635. } else {
  4636. Store_field( pntr, 0, Val_Window(root) );
  4637. Store_field( pntr, 1, Val_int(root_x) );
  4638. Store_field( pntr, 2, Val_int(root_y) );
  4639. Store_field( pntr, 3, Val_none );
  4640. Store_field( pntr, 4, Val_state_mask(mask) );
  4641. }
  4642. CAMLreturn( pntr );
  4643. }
  4644. CAMLprim value
  4645. ml_XGetKeyboardControl( value dpy )
  4646. {
  4647. CAMLparam1( dpy );
  4648. CAMLlocal2( tpl, ml_auto_repeats );
  4649. XKeyboardState kbs;
  4650. GET_STATUS XGetKeyboardControl(
  4651. Display_val(dpy),
  4652. &kbs );
  4653. CHECK_STATUS(XGetKeyboardControl,1);
  4654. tpl = caml_alloc(7, 0);
  4655. ml_auto_repeats = caml_alloc_string(32);
  4656. memcpy(String_val(ml_auto_repeats), kbs.auto_repeats, 32);
  4657. Store_field( tpl, 0, Val_int(kbs.key_click_percent) );
  4658. Store_field( tpl, 1, Val_int(kbs.bell_percent) );
  4659. Store_field( tpl, 2, Val_uint(kbs.bell_pitch) );
  4660. Store_field( tpl, 3, Val_uint(kbs.bell_duration) );
  4661. Store_field( tpl, 4, Val_ulong(kbs.led_mask) ); // TODO: WRAP ME
  4662. Store_field( tpl, 5, Val_int( (kbs.global_auto_repeat == AutoRepeatModeOff ? 0 : 1)) );
  4663. Store_field( tpl, 6, ml_auto_repeats );
  4664. CAMLreturn( tpl );
  4665. }
  4666. #if 0
  4667. static const unsigned int keyboardcontrol_table[] = {
  4668. KBKeyClickPercent,
  4669. KBBellPercent,
  4670. KBBellPitch,
  4671. KBBellDuration,
  4672. KBLed,
  4673. KBLedMode,
  4674. KBKey,
  4675. KBAutoRepeatMode,
  4676. };
  4677. #define keyboardcontrol_mask_val(i) (keyboardcontrol_table[Long_val(i)])
  4678. /* TODO
  4679. if (mask & KBKeyClickPercent) *value++ = value_list->key_click_percent;
  4680. if (mask & KBBellPercent) *value++ = value_list->bell_percent;
  4681. if (mask & KBBellPitch) *value++ = value_list->bell_pitch;
  4682. if (mask & KBBellDuration) *value++ = value_list->bell_duration;
  4683. if (mask & KBLed) *value++ = value_list->led;
  4684. if (mask & KBLedMode) *value++ = value_list->led_mode;
  4685. if (mask & KBKey) *value++ = value_list->key;
  4686. if (mask & KBAutoRepeatMode) *value++ = value_list->auto_repeat_mode;
  4687. typedef struct {
  4688. int key_click_percent;
  4689. int bell_percent;
  4690. int bell_pitch;
  4691. int bell_duration;
  4692. int led;
  4693. int led_mode;
  4694. int key;
  4695. int auto_repeat_mode; // On, Off, Default
  4696. } XKeyboardControl;
  4697. */
  4698. CAMLprim value
  4699. ml_XChangeKeyboardControl( value dpy, value ml_xkeyboardcontrol_tpl )
  4700. {
  4701. unsigned long value_mask;
  4702. while ( em_list != Val_emptylist )
  4703. {
  4704. value head = Field(em_list, 0);
  4705. long mask = keyboardcontrol_mask_val(head);
  4706. value_mask |= mask;
  4707. em_list = Field(em_list, 1);
  4708. }
  4709. //GET_STATUS
  4710. XChangeKeyboardControl(
  4711. Display_val(dpy),
  4712. value_mask,
  4713. XKeyboardControl* values
  4714. );
  4715. //CHECK_STATUS(XChangeKeyboardControl,1);
  4716. return Val_unit;
  4717. }
  4718. #endif
  4719. CAMLprim value
  4720. ml_XChangeKeyboardControl_bell_percent( value dpy, value ml_bell_percent )
  4721. {
  4722. XKeyboardControl keyboard_control_values;
  4723. keyboard_control_values.bell_percent = Int_val(ml_bell_percent);
  4724. //GET_STATUS
  4725. XChangeKeyboardControl(
  4726. Display_val(dpy),
  4727. KBBellPercent,
  4728. &keyboard_control_values
  4729. );
  4730. //CHECK_STATUS(XChangeKeyboardControl,1);
  4731. return Val_unit;
  4732. }
  4733. CAMLprim value
  4734. ml_XChangeKeyboardControl_bell_pitch( value dpy, value ml_bell_pitch )
  4735. {
  4736. XKeyboardControl keyboard_control_values;
  4737. keyboard_control_values.bell_pitch = Int_val(ml_bell_pitch);
  4738. //GET_STATUS
  4739. XChangeKeyboardControl(
  4740. Display_val(dpy),
  4741. KBBellPitch,
  4742. &keyboard_control_values
  4743. );
  4744. //CHECK_STATUS(XChangeKeyboardControl,1);
  4745. return Val_unit;
  4746. }
  4747. CAMLprim value
  4748. ml_XChangeKeyboardControl_bell_duration( value dpy, value ml_bell_duration )
  4749. {
  4750. XKeyboardControl keyboard_control_values;
  4751. keyboard_control_values.bell_duration = Int_val(ml_bell_duration);
  4752. //GET_STATUS
  4753. XChangeKeyboardControl(
  4754. Display_val(dpy),
  4755. KBBellDuration,
  4756. &keyboard_control_values
  4757. );
  4758. //CHECK_STATUS(XChangeKeyboardControl,1);
  4759. return Val_unit;
  4760. }
  4761. CAMLprim value
  4762. ml_XChangeKeyboardControl_bell(
  4763. value dpy,
  4764. value ml_bell_percent,
  4765. value ml_bell_pitch,
  4766. value ml_bell_duration )
  4767. {
  4768. XKeyboardControl keyboard_control_values;
  4769. keyboard_control_values.bell_percent = Int_val(ml_bell_percent);
  4770. keyboard_control_values.bell_pitch = Int_val(ml_bell_pitch);
  4771. keyboard_control_values.bell_duration = Int_val(ml_bell_duration);
  4772. //GET_STATUS
  4773. XChangeKeyboardControl(
  4774. Display_val(dpy),
  4775. KBBellPercent &
  4776. KBBellPitch &
  4777. KBBellDuration,
  4778. &keyboard_control_values
  4779. );
  4780. //CHECK_STATUS(XChangeKeyboardControl,1);
  4781. return Val_unit;
  4782. }
  4783. CAMLprim value
  4784. ml_XChangeKeyboardControl_key_click_percent( value dpy, value ml_key_click_percent )
  4785. {
  4786. XKeyboardControl keyboard_control_values;
  4787. keyboard_control_values.key_click_percent = Int_val(ml_key_click_percent);
  4788. //GET_STATUS
  4789. XChangeKeyboardControl(
  4790. Display_val(dpy),
  4791. KBKeyClickPercent,
  4792. &keyboard_control_values
  4793. );
  4794. //CHECK_STATUS(XChangeKeyboardControl,1);
  4795. return Val_unit;
  4796. }
  4797. /* TODO: place */
  4798. CAMLprim value
  4799. ml_XChangePointerControl(
  4800. value dpy,
  4801. value do_accel,
  4802. value do_threshold,
  4803. value accel_numerator,
  4804. value accel_denominator,
  4805. value threshold )
  4806. {
  4807. //GET_STATUS
  4808. XChangePointerControl(
  4809. Display_val(dpy),
  4810. Bool_val(do_accel),
  4811. Bool_val(do_threshold),
  4812. Int_val(accel_numerator),
  4813. Int_val(accel_denominator),
  4814. Int_val(threshold)
  4815. );
  4816. //CHECK_STATUS(XChangePointerControl,1);
  4817. return Val_unit;
  4818. }
  4819. CAMLprim value
  4820. ml_XChangePointerControl_bytecode( value * argv, int argn )
  4821. {
  4822. return ml_XChangePointerControl( argv[0], argv[1], argv[2],
  4823. argv[3], argv[4], argv[5] );
  4824. }
  4825. CAMLprim value
  4826. ml_XGetPointerControl( value dpy )
  4827. {
  4828. CAMLparam1(dpy);
  4829. CAMLlocal1( pnt_ctrl );
  4830. int accel_numerator;
  4831. int accel_denominator;
  4832. int threshold;
  4833. //GET_STATUS
  4834. XGetPointerControl(
  4835. Display_val(dpy),
  4836. &accel_numerator,
  4837. &accel_denominator,
  4838. &threshold
  4839. );
  4840. //CHECK_STATUS(XGetPointerControl, TODO );
  4841. pnt_ctrl = caml_alloc(3, 0);
  4842. Store_field( pnt_ctrl, 0, Val_int(accel_numerator) );
  4843. Store_field( pnt_ctrl, 1, Val_int(accel_denominator) );
  4844. Store_field( pnt_ctrl, 2, Val_int(threshold) );
  4845. CAMLreturn( pnt_ctrl );
  4846. }
  4847. /* ScreenSaver */
  4848. CAMLprim value
  4849. ml_XForceScreenSaver( value dpy, value mode )
  4850. {
  4851. GET_STATUS XForceScreenSaver(
  4852. Display_val(dpy),
  4853. ( Long_val(mode) ? ScreenSaverReset : ScreenSaverActive )
  4854. );
  4855. CHECK_STATUS(XForceScreenSaver,1);
  4856. return Val_unit;
  4857. }
  4858. static const int prefer_blanking_table[] = {
  4859. DontPreferBlanking,
  4860. PreferBlanking,
  4861. DefaultBlanking
  4862. };
  4863. #define Prefer_blanking_val(i) (prefer_blanking_table[Long_val(i)])
  4864. static inline value Val_prefer_blanking(int v) {
  4865. switch (v) {
  4866. case DontPreferBlanking: return Val_int(0);
  4867. case PreferBlanking: return Val_int(1);
  4868. case DefaultBlanking: return Val_int(2);
  4869. }
  4870. return Val_int(0);
  4871. }
  4872. static const int allow_exposures_table[] = {
  4873. DontAllowExposures,
  4874. AllowExposures,
  4875. DefaultExposures
  4876. };
  4877. #define Allow_exposures_val(i) (allow_exposures_table[Long_val(i)])
  4878. static inline value Val_allow_exposures(int v) {
  4879. switch (v) {
  4880. case DontAllowExposures: return Val_int(0);
  4881. case AllowExposures: return Val_int(1);
  4882. case DefaultExposures: return Val_int(2);
  4883. }
  4884. return Val_int(0);
  4885. }
  4886. CAMLprim value
  4887. ml_XGetScreenSaver( value dpy )
  4888. {
  4889. CAMLparam1( dpy );
  4890. CAMLlocal1( tpl );
  4891. int timeout;
  4892. int interval;
  4893. int prefer_blanking;
  4894. int allow_exposures;
  4895. GET_STATUS XGetScreenSaver(
  4896. Display_val(dpy),
  4897. &timeout,
  4898. &interval,
  4899. &prefer_blanking,
  4900. &allow_exposures
  4901. );
  4902. CHECK_STATUS(XGetScreenSaver,1);
  4903. tpl = caml_alloc(4, 0);
  4904. Store_field( tpl, 0, Val_int(timeout) );
  4905. Store_field( tpl, 1, Val_int(interval) );
  4906. Store_field( tpl, 2, Val_prefer_blanking(prefer_blanking) );
  4907. Store_field( tpl, 3, Val_allow_exposures(allow_exposures) );
  4908. CAMLreturn( tpl );
  4909. }
  4910. CAMLprim value
  4911. ml_XSetScreenSaver(
  4912. value dpy,
  4913. value timeout,
  4914. value interval,
  4915. value prefer_blanking,
  4916. value allow_exposures )
  4917. {
  4918. //GET_STATUS
  4919. XSetScreenSaver(
  4920. Display_val(dpy),
  4921. Int_val(timeout),
  4922. Int_val(interval),
  4923. Prefer_blanking_val(prefer_blanking),
  4924. Allow_exposures_val(allow_exposures)
  4925. );
  4926. //CHECK_STATUS(XSetScreenSaver,1);
  4927. return Val_unit;
  4928. }
  4929. CAMLprim value
  4930. ml_XActivateScreenSaver( value dpy )
  4931. {
  4932. //GET_STATUS
  4933. XActivateScreenSaver( Display_val(dpy) );
  4934. //CHECK_STATUS(XActivateScreenSaver,1);
  4935. return Val_unit;
  4936. }
  4937. CAMLprim value
  4938. ml_XResetScreenSaver( value dpy )
  4939. {
  4940. //GET_STATUS
  4941. XResetScreenSaver( Display_val(dpy) );
  4942. //CHECK_STATUS(XResetScreenSaver,1);
  4943. return Val_unit;
  4944. }
  4945. /* {{{ (Screen *) */
  4946. CAMLprim value
  4947. ml_XDefaultScreenOfDisplay( value dpy )
  4948. {
  4949. Screen *scr = _xDefaultScreenOfDisplay(
  4950. Display_val(dpy) );
  4951. return Val_XScreen(scr);
  4952. }
  4953. CAMLprim value
  4954. ml_XScreenOfDisplay( value dpy, value screen_number )
  4955. {
  4956. Screen *scr = _xScreenOfDisplay(
  4957. Display_val(dpy),
  4958. ScreenNB_val(screen_number) );
  4959. return Val_XScreen(scr);
  4960. }
  4961. CAMLprim value
  4962. ml_XDefaultVisualOfScreen( value xscreen )
  4963. {
  4964. Visual *visual = _xDefaultVisualOfScreen(
  4965. XScreen_val(xscreen) );
  4966. return Val_Visual(visual);
  4967. }
  4968. CAMLprim value
  4969. ml_XRootWindowOfScreen( value xscreen )
  4970. {
  4971. return Val_Window( _xRootWindowOfScreen( XScreen_val(xscreen) ));
  4972. }
  4973. CAMLprim value
  4974. ml_XBlackPixelOfScreen( value xscreen )
  4975. {
  4976. unsigned long px = _xBlackPixelOfScreen(
  4977. XScreen_val(xscreen)
  4978. );
  4979. return Val_pixel_color(px);
  4980. }
  4981. CAMLprim value
  4982. ml_XWhitePixelOfScreen( value xscreen )
  4983. {
  4984. unsigned long px = _xWhitePixelOfScreen(
  4985. XScreen_val(xscreen)
  4986. );
  4987. return Val_pixel_color(px);
  4988. }
  4989. CAMLprim value
  4990. ml_XDefaultColormapOfScreen( value xscreen )
  4991. {
  4992. Colormap cmap = _xDefaultColormapOfScreen(
  4993. XScreen_val(xscreen)
  4994. );
  4995. return Val_Colormap(cmap);
  4996. }
  4997. CAMLprim value
  4998. ml_XDefaultDepthOfScreen( value xscreen )
  4999. {
  5000. return Val_int( _xDefaultDepthOfScreen( XScreen_val(xscreen) ));
  5001. }
  5002. CAMLprim value
  5003. ml_XDefaultGCOfScreen( value xscreen )
  5004. {
  5005. GC gc = _xDefaultGCOfScreen( XScreen_val(xscreen) );
  5006. Display *dpy = _xDisplayOfScreen( XScreen_val(xscreen) );
  5007. return Val_GC(gc, Val_Display(dpy));
  5008. }
  5009. CAMLprim value
  5010. ml_XDisplayOfScreen( value xscreen )
  5011. {
  5012. Display *dpy = _xDisplayOfScreen(
  5013. XScreen_val(xscreen)
  5014. );
  5015. return Val_Display(dpy);
  5016. }
  5017. CAMLprim value
  5018. ml_XWidthOfScreen( value xscreen )
  5019. {
  5020. return Val_int( _xWidthOfScreen( XScreen_val(xscreen) ));
  5021. }
  5022. CAMLprim value
  5023. ml_XHeightOfScreen( value xscreen )
  5024. {
  5025. return Val_int( _xHeightOfScreen( XScreen_val(xscreen) ));
  5026. }
  5027. CAMLprim value
  5028. ml_XScreenNumberOfScreen( value xscreen )
  5029. {
  5030. return Val_screenNB( XScreenNumberOfScreen( XScreen_val(xscreen) ));
  5031. }
  5032. /* }}} */
  5033. /* {{{ ICCCM routines */
  5034. #if 0
  5035. Status XReconfigureWMWindow(
  5036. Display* /* display */,
  5037. Window /* w */,
  5038. int /* screen_number */,
  5039. unsigned int /* mask */,
  5040. XWindowChanges* /* changes */
  5041. );
  5042. Status XGetWMProtocols(
  5043. Display* /* display */,
  5044. Window /* w */,
  5045. Atom** /* protocols_return */,
  5046. int* /* count_return */
  5047. );
  5048. Status XSetWMProtocols(
  5049. Display* /* display */,
  5050. Window /* w */,
  5051. Atom* /* protocols */,
  5052. int /* count */
  5053. );
  5054. #endif
  5055. CAMLprim value
  5056. ml_XIconifyWindow( value dpy, value win, value screen_number )
  5057. {
  5058. GET_STATUS XIconifyWindow(
  5059. Display_val(dpy),
  5060. Window_val(win),
  5061. ScreenNB_val(screen_number)
  5062. );
  5063. CHECK_STATUS(XIconifyWindow,1);
  5064. return Val_unit;
  5065. }
  5066. CAMLprim value
  5067. ml_XWithdrawWindow( value dpy, value win, value screen_number )
  5068. {
  5069. GET_STATUS XWithdrawWindow(
  5070. Display_val(dpy),
  5071. Window_val(win),
  5072. ScreenNB_val(screen_number)
  5073. );
  5074. CHECK_STATUS(XWithdrawWindow,1);
  5075. return Val_unit;
  5076. }
  5077. CAMLprim value
  5078. ml_XGetCommand( value dpy, value win )
  5079. {
  5080. CAMLparam2(dpy, win);
  5081. CAMLlocal1(cmds);
  5082. char** argv;
  5083. int argc = 0;
  5084. Status st = XGetCommand(
  5085. Display_val(dpy),
  5086. Window_val(win),
  5087. &argv,
  5088. &argc
  5089. );
  5090. if (!st) {
  5091. cmds = caml_alloc(0, 0); // return an empty array instead of an exception
  5092. } else {
  5093. int i;
  5094. cmds = caml_alloc(argc, 0);
  5095. for (i=0; i<argc; ++i) {
  5096. Store_field(cmds, i, caml_copy_string(argv[i]));
  5097. }
  5098. XFreeStringList(argv);
  5099. }
  5100. CAMLreturn(cmds);
  5101. }
  5102. #if 0
  5103. Status XGetWMColormapWindows(
  5104. Display* /* display */,
  5105. Window /* w */,
  5106. Window** /* windows_return */,
  5107. int* /* count_return */
  5108. );
  5109. Status XSetWMColormapWindows(
  5110. Display* /* display */,
  5111. Window /* w */,
  5112. Window* /* colormap_windows */,
  5113. int /* count */
  5114. );
  5115. void XFreeStringList(
  5116. char** /* list */
  5117. );
  5118. int XSetTransientForHint(
  5119. Display* /* display */,
  5120. Window /* w */,
  5121. Window /* prop_window */
  5122. );
  5123. #endif
  5124. /* }}} */
  5125. /* {{{ Cursor */
  5126. /*
  5127. XC_arrow,
  5128. XC_top_left_arrow,
  5129. XC_hand1,
  5130. XC_pirate,
  5131. XC_question_arrow,
  5132. XC_exchange,
  5133. XC_spraycan,
  5134. XC_watch,
  5135. XC_xterm,
  5136. XC_crosshair,
  5137. XC_sb_v_double_arrow,
  5138. XC_sb_h_double_arrow,
  5139. XC_top_side,
  5140. XC_bottom_side,
  5141. XC_left_side,
  5142. XC_right_side,
  5143. XC_top_left_corner,
  5144. XC_top_right_corner,
  5145. XC_bottom_right_corner,
  5146. XC_bottom_left_corner,
  5147. */
  5148. #include <X11/cursorfont.h>
  5149. static const unsigned int cursor_shape_table[] = {
  5150. XC_X_cursor,
  5151. XC_arrow,
  5152. XC_based_arrow_down,
  5153. XC_based_arrow_up,
  5154. XC_boat,
  5155. XC_bogosity,
  5156. XC_bottom_left_corner,
  5157. XC_bottom_right_corner,
  5158. XC_bottom_side,
  5159. XC_bottom_tee,
  5160. XC_box_spiral,
  5161. XC_center_ptr,
  5162. XC_circle,
  5163. XC_clock,
  5164. XC_coffee_mug,
  5165. XC_cross,
  5166. XC_cross_reverse,
  5167. XC_crosshair,
  5168. XC_diamond_cross,
  5169. XC_dot,
  5170. XC_dotbox,
  5171. XC_double_arrow,
  5172. XC_draft_large,
  5173. XC_draft_small,
  5174. XC_draped_box,
  5175. XC_exchange,
  5176. XC_fleur,
  5177. XC_gobbler,
  5178. XC_gumby,
  5179. XC_hand1,
  5180. XC_hand2,
  5181. XC_heart,
  5182. XC_icon,
  5183. XC_iron_cross,
  5184. XC_left_ptr,
  5185. XC_left_side,
  5186. XC_left_tee,
  5187. XC_leftbutton,
  5188. XC_ll_angle,
  5189. XC_lr_angle,
  5190. XC_man,
  5191. XC_middlebutton,
  5192. XC_mouse,
  5193. XC_pencil,
  5194. XC_pirate,
  5195. XC_plus,
  5196. XC_question_arrow,
  5197. XC_right_ptr,
  5198. XC_right_side,
  5199. XC_right_tee,
  5200. XC_rightbutton,
  5201. XC_rtl_logo,
  5202. XC_sailboat,
  5203. XC_sb_down_arrow,
  5204. XC_sb_h_double_arrow,
  5205. XC_sb_left_arrow,
  5206. XC_sb_right_arrow,
  5207. XC_sb_up_arrow,
  5208. XC_sb_v_double_arrow,
  5209. XC_shuttle,
  5210. XC_sizing,
  5211. XC_spider,
  5212. XC_spraycan,
  5213. XC_star,
  5214. XC_target,
  5215. XC_tcross,
  5216. XC_top_left_arrow,
  5217. XC_top_left_corner,
  5218. XC_top_right_corner,
  5219. XC_top_side,
  5220. XC_top_tee,
  5221. XC_trek,
  5222. XC_ul_angle,
  5223. XC_umbrella,
  5224. XC_ur_angle,
  5225. XC_watch,
  5226. XC_xterm,
  5227. };
  5228. CAMLprim value
  5229. ml_XCreateFontCursor( value dpy, value shape )
  5230. {
  5231. Cursor cur = XCreateFontCursor(
  5232. Display_val(dpy),
  5233. cursor_shape_table[ Long_val(shape) ]
  5234. );
  5235. return Val_Cursor(cur);
  5236. }
  5237. CAMLprim value
  5238. ml_XDefineCursor( value dpy, value win, value cur )
  5239. {
  5240. //GET_STATUS
  5241. XDefineCursor(
  5242. Display_val(dpy),
  5243. Window_val(win),
  5244. Cursor_val(cur)
  5245. );
  5246. //CHECK_STATUS(XDefineCursor,1);
  5247. return Val_unit;
  5248. }
  5249. CAMLprim value
  5250. ml_XRecolorCursor( value dpy, value cur, value foreground, value background )
  5251. {
  5252. //GET_STATUS
  5253. XRecolorCursor(
  5254. Display_val(dpy),
  5255. Cursor_val(cur),
  5256. XColor_val(foreground),
  5257. XColor_val(background)
  5258. );
  5259. //CHECK_STATUS(XRecolorCursor,1);
  5260. return Val_unit;
  5261. }
  5262. /* }}} */
  5263. /* {{{ Font */
  5264. #define XFontStruct_val(v) ((XFontStruct *)(v))
  5265. #define Val_XFontStruct(fs) ((value)(fs))
  5266. CAMLprim value
  5267. ml_XSetFont( value dpy, value gc, value font )
  5268. {
  5269. //GET_STATUS
  5270. XSetFont(
  5271. Display_val(dpy),
  5272. GC_val(gc),
  5273. Font_val(font)
  5274. );
  5275. //CHECK_STATUS(XSetFont,1);
  5276. return Val_unit;
  5277. }
  5278. CAMLprim value
  5279. ml_XLoadQueryFont( value dpy, value name )
  5280. {
  5281. XFontStruct *fs = XLoadQueryFont(
  5282. Display_val(dpy),
  5283. String_val(name)
  5284. );
  5285. return Val_XFontStruct(fs);
  5286. }
  5287. CAMLprim value
  5288. ml_XQueryFont( value dpy, value font )
  5289. {
  5290. XFontStruct *fs = XQueryFont(
  5291. Display_val(dpy),
  5292. Font_val(font)
  5293. );
  5294. return Val_XFontStruct(fs);
  5295. }
  5296. CAMLprim value
  5297. ml_XQueryFontGC( value dpy, value gc )
  5298. {
  5299. XFontStruct *fs = XQueryFont(
  5300. Display_val(dpy),
  5301. XGContextFromGC(GC_val(gc))
  5302. );
  5303. return Val_XFontStruct(fs);
  5304. }
  5305. #if 0
  5306. XFontStruct {
  5307. XExtData *ext_data; /* hook for extension to hang data */
  5308. Font fid; /* Font id for this font */
  5309. unsigned direction; /* hint about direction the font is painted */
  5310. unsigned min_char_or_byte2;/* first character */
  5311. unsigned max_char_or_byte2;/* last character */
  5312. unsigned min_byte1; /* first row that exists */
  5313. unsigned max_byte1; /* last row that exists */
  5314. Bool all_chars_exist;/* flag if all characters have non-zero size*/
  5315. unsigned default_char; /* char to print for undefined character */
  5316. int n_properties; /* how many properties there are */
  5317. XFontProp *properties; /* pointer to array of additional properties*/
  5318. XCharStruct min_bounds; /* minimum bounds over all existing char*/
  5319. XCharStruct max_bounds; /* maximum bounds over all existing char*/
  5320. XCharStruct *per_char; /* first_char to last_char information */
  5321. int ascent; /* log. extent above baseline for spacing */
  5322. int descent; /* log. descent below baseline for spacing */
  5323. }
  5324. #endif
  5325. #define FNTST_GET(field_c_type, field_name, Val_conv, ml_type) \
  5326. \
  5327. CAMLprim value \
  5328. ml_XFontStruct_get_##field_name( value vfs ) \
  5329. { \
  5330. return Val_conv((XFontStruct_val(vfs))->field_name); \
  5331. }
  5332. #define FNTST_GML(field_c_type, field_name, Val_conv, ml_type) \
  5333. external xFontStruct_##field_name: xFontStruct -> ml_type = quote(ml_XFontStruct_get_##field_name)
  5334. FNTST_GET(Font, fid, Val_Font, font)
  5335. FNTST_GET(int, ascent, Val_int, int)
  5336. FNTST_GET(int, descent, Val_int, int)
  5337. FNTST_GET(Bool, all_chars_exist, Val_bool, bool)
  5338. CAMLprim value
  5339. ml_XFontStruct_get_height( value vfs )
  5340. {
  5341. CAMLparam1( vfs );
  5342. CAMLlocal1( height );
  5343. XFontStruct * fs = XFontStruct_val(vfs);
  5344. height = caml_alloc(2, 0);
  5345. Store_field( height, 0, Val_int(fs->ascent) );
  5346. Store_field( height, 1, Val_int(fs->descent) );
  5347. CAMLreturn( height );
  5348. }
  5349. CAMLprim value
  5350. ml_XFontStruct_get_height2( value dpy, value gc )
  5351. {
  5352. CAMLparam2( dpy, gc );
  5353. CAMLlocal1( height );
  5354. XFontStruct *fs = XQueryFont(
  5355. Display_val(dpy),
  5356. XGContextFromGC(GC_val(gc))
  5357. );
  5358. if (!fs)
  5359. caml_failwith("XFontStruct");
  5360. height = caml_alloc(2, 0);
  5361. Store_field( height, 0, Val_int(fs->ascent) );
  5362. Store_field( height, 1, Val_int(fs->descent) );
  5363. CAMLreturn( height );
  5364. }
  5365. CAMLprim value
  5366. ml_XTextWidth( value vfs, value str )
  5367. {
  5368. XFontStruct * fs = XFontStruct_val(vfs);
  5369. //if (fs == NULL)
  5370. // caml_invalid_argument("xTextWidth");
  5371. return Val_int( XTextWidth(
  5372. fs,
  5373. String_val(str),
  5374. caml_string_length(str)
  5375. ));
  5376. }
  5377. CAMLprim value
  5378. ml_xFontStruct_max_bounds( value vfs )
  5379. {
  5380. CAMLparam1( vfs );
  5381. CAMLlocal1( cst );
  5382. XFontStruct * fs = XFontStruct_val(vfs);
  5383. XCharStruct * b = &(fs->max_bounds);
  5384. cst = caml_alloc(5, 0);
  5385. Store_field( cst, 0, Val_int(b->lbearing) );
  5386. Store_field( cst, 1, Val_int(b->rbearing) );
  5387. Store_field( cst, 2, Val_int(b->width) );
  5388. Store_field( cst, 3, Val_int(b->ascent) );
  5389. Store_field( cst, 4, Val_int(b->descent) );
  5390. CAMLreturn( cst );
  5391. }
  5392. CAMLprim value
  5393. ml_xFontStruct_min_bounds( value vfs )
  5394. {
  5395. CAMLparam1( vfs );
  5396. CAMLlocal1( cst );
  5397. XFontStruct * fs = XFontStruct_val(vfs);
  5398. XCharStruct * b = &(fs->min_bounds);
  5399. cst = caml_alloc(5, 0);
  5400. Store_field( cst, 0, Val_int(b->lbearing) );
  5401. Store_field( cst, 1, Val_int(b->rbearing) );
  5402. Store_field( cst, 2, Val_int(b->width) );
  5403. Store_field( cst, 3, Val_int(b->ascent) );
  5404. Store_field( cst, 4, Val_int(b->descent) );
  5405. CAMLreturn( cst );
  5406. }
  5407. /*
  5408. int XTextWidth16(
  5409. XFontStruct* font_struct,
  5410. _Xconst XChar2b* string,
  5411. int count );
  5412. */
  5413. /* }}} */
  5414. // vim: sw=4 sts=4 ts=4 et fdm=marker