]> git.mdlowis.com Git - archive/tide-ocaml.git/commitdiff
implemented skeleton event loop as an x11 primitive
authorMichael D. Lowis <mike@mdlowis.com>
Fri, 1 Sep 2017 01:57:52 +0000 (21:57 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Fri, 1 Sep 2017 01:57:52 +0000 (21:57 -0400)
edit.ml
lib/x11.ml
lib/x11_prims.c

diff --git a/edit.ml b/edit.ml
index d21b23b7716dd5b0e1fe5a81a746c6033f7ce10a..c26e8e4c89ca52de6af3224797060143f619749f 100644 (file)
--- a/edit.ml
+++ b/edit.ml
@@ -1,6 +1,9 @@
 let () =
   X11.make_window 640 480;
   X11.show_window true;
+  X11.event_loop 50 (fun x -> print_endline "event")
+
+(*
   let server = Tide.start_server () in
   let nargs = Array.length Sys.argv in
   for i = 1 to (nargs - 1) do
@@ -10,3 +13,4 @@ let () =
     else
       Tide.edit_file server arg
   done;
+*)
index 05aab11097619c642b4aa0fa79743e6e40cd63fc..6ca2a4ecc11634bfb083455540c0264322458fa9 100644 (file)
@@ -1,7 +1,7 @@
 type xatom
 type xwin
 type xevent =
-    Focus of { focused: bool }
+  | Focus of { focused: bool }
   | KeyPress of { mods: int; rune: int }
   | MouseBtn of {
       mods: int;
@@ -16,6 +16,12 @@ type xevent =
   | Resize of { height: int; width: int }
   | Shutdown
   | QueueEmpty
+  | Filtered
+(*
+  | PipeClosed
+  | PipeWriteReady
+  | PipeReadReady
+*)
 
 external connect : unit -> unit
                  = "x11_connect"
@@ -35,8 +41,11 @@ external make_dialog : int -> int -> unit
 external show_window : bool -> unit
                   = "x11_show_window"
 
-external has_event : unit -> bool
-                   = "x11_has_event"
+external event_loop : int -> (xevent -> unit) -> unit
+                   = "x11_event_loop"
+
+external num_events : unit -> int
+                   = "x11_num_events"
 
 external next_event : unit -> xevent
                    = "x11_next_event"
@@ -54,10 +63,10 @@ external prop_get : xwin -> xatom -> string
                   = "x11_prop_get"
 
 (* to be implemented
-external sel_set : atom -> string -> unit
-                  = "x11_sel_set"
-external sel_get : atom -> unit
-                 = "x11_sel_get"
+external sel_set : xatom -> string -> unit
+                 = "x11_sel_set"
+external sel_fetch : xatom -> unit
+                   = "x11_sel_get"
 *)
 
 (* Automatically connect and disconnect to the display server *)
index 1338e5430e55bfb6b37f7e5355bd94d282f6d421..7918004b93fb1898690f1ab9dfd8a887033b4d8e 100644 (file)
@@ -3,7 +3,7 @@
 #include <caml/fail.h>
 #include <caml/memory.h>
 #include <caml/alloc.h>
-//#include <caml/custom.h>
+#include <caml/callback.h>
 
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
@@ -14,6 +14,7 @@ static char* readprop(Window win, Atom prop);
 static void create_window(int height, int width);
 
 static struct {
+    bool running;
     Display* display;
     Visual* visual;
     Colormap colormap;
@@ -30,26 +31,35 @@ static struct {
     XIC xic;
     XIM xim;
     GC gc;
-} X;
+} X = {0};
 
 CAMLprim value x11_connect(void) {
     CAMLparam0();
-    if (!(X.display = XOpenDisplay(NULL)))
-        caml_failwith("could not open display");
-    XSetErrorHandler(error_handler);
-    X.root = DefaultRootWindow(X.display);
-    XWindowAttributes wa;
-    XGetWindowAttributes(X.display, X.root, &wa);
-    X.visual   = wa.visual;
-    X.colormap = wa.colormap;
-    X.screen   = DefaultScreen(X.display);
-    X.depth    = DefaultDepth(X.display, X.screen);
+    if (!X.display) {
+        if (!(X.display = XOpenDisplay(NULL)))
+            caml_failwith("could not open display");
+        XSetErrorHandler(error_handler);
+        X.root = DefaultRootWindow(X.display);
+        XWindowAttributes wa;
+        XGetWindowAttributes(X.display, X.root, &wa);
+        X.visual   = wa.visual;
+        X.colormap = wa.colormap;
+        X.screen   = DefaultScreen(X.display);
+        X.depth    = DefaultDepth(X.display, X.screen);
+        X.running  = true;
+    }
     CAMLreturn(Val_unit);
 }
 
 CAMLprim value x11_disconnect(void) {
     CAMLparam0();
-    XCloseDisplay(X.display);
+    if (X.display) {
+        if (X.self) {
+            XUnmapWindow(X.display, X.self);
+            XSync(X.display, True);
+        }
+        XCloseDisplay(X.display);
+    }
     CAMLreturn(Val_unit);
 }
 
@@ -75,16 +85,39 @@ CAMLprim value x11_make_dialog(value height, value width) {
 
 CAMLprim value x11_show_window(value state) {
     CAMLparam1(state);
-    if (Bool_val(state)) {
-        /* simulate an initial resize and map the window */
-        XConfigureEvent ce;
-        ce.type   = ConfigureNotify;
-        ce.width  = X.width;
-        ce.height = X.height;
-        XSendEvent(X.display, X.self, False, StructureNotifyMask, (XEvent *)&ce);
+    if (Bool_val(state))
         XMapWindow(X.display, X.self);
-    } else {
+    else
         XUnmapWindow(X.display, X.self);
+    CAMLreturn(Val_unit);
+}
+
+CAMLprim value x11_event_loop(value ms, value cbfn) {
+    CAMLparam2(ms, cbfn);
+    while (X.running) {
+        XEvent e; XPeekEvent(X.display, &e);
+        bool pending = false; //pollfds(Int_val(ms), cbfn);
+        int nevents  = XEventsQueued(X.display, QueuedAfterFlush);
+        if (pending || nevents) {
+            /* pare down irrelevant mouse drag events to just the latest */
+            XTimeCoord* coords = XGetMotionEvents(X.display, X.self, CurrentTime, CurrentTime, &nevents);
+            if (coords) XFree(coords);
+
+            /* now take the events, convert them, and call the callback */
+            for (XEvent e; XPending(X.display);) {
+                XNextEvent(X.display, &e);
+                if (!XFilterEvent(&e, None)) {
+                    // Convert the event.
+                    caml_callback(cbfn, Val_unit);
+                }
+            }
+
+            if (X.running) {
+                caml_callback(cbfn, Val_unit /* redraw event */);
+                XCopyArea(X.display, X.pixmap, X.self, X.gc, 0, 0, X.width, X.height, 0, 0);
+            }
+        }
+        XFlush(X.display);
     }
     CAMLreturn(Val_unit);
 }
@@ -137,7 +170,7 @@ static void create_window(int height, int width) {
     XGetWindowAttributes(X.display, X.root, &wa);
     X.self = XCreateSimpleWindow(X.display, X.root,
         (wa.width  - X.width) / 2,
-        (wa.height - X.height) /2,
+        (wa.height - X.height) / 2,
         X.width,
         X.height,
         0, X.depth,
@@ -153,7 +186,7 @@ static void create_window(int height, int width) {
     swa.backing_store = WhenMapped;
     swa.bit_gravity = NorthWestGravity;
     XChangeWindowAttributes(X.display, X.self, CWBackingStore|CWBitGravity, &swa);
-    XStoreName(X.display, X.self, "tide");
+    //XStoreName(X.display, X.self, "tide");
     XSelectInput(X.display, X.self,
           StructureNotifyMask
         | ButtonPressMask