From: Michael D. Lowis Date: Fri, 1 Sep 2017 01:57:52 +0000 (-0400) Subject: implemented skeleton event loop as an x11 primitive X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=accea33c34f2239fd415b2cf7d7df7c120d9b216;p=archive%2Ftide-ocaml.git implemented skeleton event loop as an x11 primitive --- diff --git a/edit.ml b/edit.ml index d21b23b..c26e8e4 100644 --- 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; +*) diff --git a/lib/x11.ml b/lib/x11.ml index 05aab11..6ca2a4e 100644 --- a/lib/x11.ml +++ b/lib/x11.ml @@ -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 *) diff --git a/lib/x11_prims.c b/lib/x11_prims.c index 1338e54..7918004 100644 --- a/lib/x11_prims.c +++ b/lib/x11_prims.c @@ -3,7 +3,7 @@ #include #include #include -//#include +#include #include #include @@ -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