Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various improvements on JS backend #150

Merged
merged 6 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/ocamlCanvas.ml
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ module V1 = struct
external createOnscreen :
?autocommit:bool -> ?decorated:bool -> ?resizeable:bool ->
?minimize:bool -> ?maximize:bool -> ?close:bool -> ?title:string ->
?pos:(int * int) -> size:(int * int) -> unit -> t
?target:string -> ?pos:(int * int) -> size:(int * int) -> unit -> t
= "ml_canvas_create_onscreen" "ml_canvas_create_onscreen_n"

external createOffscreen : size:(int * int) -> unit -> t
Expand Down
7 changes: 5 additions & 2 deletions src/ocamlCanvas.mli
Original file line number Diff line number Diff line change
Expand Up @@ -766,9 +766,9 @@ module V1 : sig
val createOnscreen :
?autocommit:bool -> ?decorated:bool -> ?resizeable:bool ->
?minimize:bool -> ?maximize:bool -> ?close:bool -> ?title:string ->
?pos:(int * int) -> size:(int * int) -> unit -> t
?target:string -> ?pos:(int * int) -> size:(int * int) -> unit -> t
(** [createOnscreen ?autocommit ?decorated ?resizeable ?minimize
?maximize ?close ?title ?pos ~size ()] creates a windowed
?maximize ?close ?title ?target ?pos ~size()] creates a windowed
canvas of size [size]. The window title and position can be
specified using the optional arguments [title] and [pos].
The window decorations, which are active by default, can
Expand All @@ -777,6 +777,9 @@ module V1 : sig
The [decorated] argument has a higher priority: if set to false,
all other decoration arguments will be ignored (considered to be
false), and all decorations will be removed from the window.
The [target] option is relevant only for the Javascript backend.
It indicates the element id in which the canvas should be placed,
default to the html body.
The [autocommit] option, which is active by default, indicates whether
the canvas should be automatically presented after each frame event.
See {!Canvas.commit} for more info on [autocommit].
Expand Down
6 changes: 4 additions & 2 deletions src/stubs/ml_canvas.c
Original file line number Diff line number Diff line change
Expand Up @@ -673,12 +673,14 @@ ml_canvas_create_onscreen_n(
value mlMaximize, /* bool, optional, default = true */
value mlClose, /* bool, optional, default = true */
value mlTitle, /* string, optional, default = "" */
value mlTarget, /* string, optional */
value mlPos, /* (int * int), optional */
value mlSize, /* (int * int), non-optional */
value mlUnit)
{
CAMLparam5(mlAutocommit, mlDecorated, mlResizeable, mlMinimize, mlMaximize);
CAMLxparam5(mlClose, mlTitle, mlPos, mlSize, mlUnit);
CAMLxparam5(mlClose, mlTitle, mlTarget, mlPos, mlSize);
CAMLxparam1(mlUnit);
CAMLlocal1(mlCanvas);
_ml_canvas_ensure_initialized();
int32_t width = Int31_val_clip(Field(mlSize, 0));
Expand Down Expand Up @@ -708,7 +710,7 @@ ml_canvas_create_onscreen_n(
CAMLreturn(mlCanvas);
}

BYTECODE_STUB_10(ml_canvas_create_onscreen)
BYTECODE_STUB_11(ml_canvas_create_onscreen)

CAMLprim value
ml_canvas_create_offscreen(
Expand Down
100 changes: 70 additions & 30 deletions src/stubs/ml_canvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ var _move = {
prev_y: 0
}

//Provides: _resize
//Requires: _resize_handler
var _resize = new window.ResizeObserver(_resize_handler);

//Provides: _event_canvas_scale
function _event_canvas_scale(e) {
return { scaleX : e.target.canvas.width / e.target.clientWidth,
scaleY : e.target.canvas.height / e.target.clientHeight
}
}

//Provides: _make_key_event
//Requires: _focus, keyname_to_keycode, Val_key_code, Val_key_state, EVENT_TAG
//Requires: caml_int64_of_float
Expand Down Expand Up @@ -108,44 +119,46 @@ function _header_down_handler(e) {
_move.target = e.target.canvas.frame;
_move.prev_x = e.pageX;
_move.prev_y = e.pageY;
document.body.insertBefore(_move.target, null);
e.target.canvas.target.insertBefore(_move.target, null);
}
return false;
}

//Provides: _surface_down_handler
//Requires: _focus, _ml_canvas_process_event, EVENT_TAG
//Requires: _focus, _ml_canvas_process_event, _event_canvas_scale, EVENT_TAG
//Requires: caml_int64_of_float
function _surface_down_handler(e) {
if (e.target !== null) {
_focus = e.target.canvas;
document.body.insertBefore(e.target.canvas.frame, null);
e.target.canvas.target.insertBefore(e.target.canvas.frame, null);
var s = _event_canvas_scale(e);
var evt = [EVENT_TAG.BUTTON_ACTION,
[0, e.target.canvas,
caml_int64_of_float(e.timeStamp * 1000.0),
[0, e.offsetX, e.offsetY], e.button + 1, 1]];
[0, e.offsetX*s.scaleX, e.offsetY*s.scaleY], e.button + 1, 1]];
_ml_canvas_process_event(evt);
}
return false;
}

//Provides: _up_handler
//Requires: _move, _ml_canvas_process_event, EVENT_TAG
//Requires: _move, _ml_canvas_process_event, _event_canvas_scale, EVENT_TAG
//Requires: caml_int64_of_float
function _up_handler(e) {
_move.moving = false;
if (e.target.canvas !== undefined) {
var s = _event_canvas_scale(e);
var evt = [EVENT_TAG.BUTTON_ACTION,
[0, e.target.canvas,
caml_int64_of_float(e.timeStamp * 1000.0),
[0, e.offsetX, e.offsetY], e.button + 1, 0]];
[0, e.offsetX*s.scaleX, e.offsetY*s.scaleY], e.button + 1, 0]];
_ml_canvas_process_event(evt);
}
return false; // = prevent default behavior
}

//Provides: _move_handler
//Requires: _move, _ml_canvas_process_event, EVENT_TAG
//Requires: _move, _ml_canvas_process_event, _event_canvas_scale, EVENT_TAG
//Requires: caml_int64_of_float
function _move_handler(e) {
if (_move.moving) {
Expand All @@ -161,15 +174,30 @@ function _move_handler(e) {
_move.target.style.left = canvas.x + "px";
_move.target.style.top = canvas.y + "px";
} else if (e.target.canvas !== undefined) {
var s = _event_canvas_scale(e);
var evt = [EVENT_TAG.MOUSE_MOVE,
[0, e.target.canvas,
caml_int64_of_float(e.timeStamp * 1000.0),
[0, e.offsetX, e.offsetY]]];
[0, e.offsetX*s.scaleX, e.offsetY*s.scaleY]]];
_ml_canvas_process_event(evt);
}
return false;
}

//Provides: _resize_handler
//Requires: _ml_canvas_process_event, EVENT_TAG
//Requires: caml_int64_of_float
function _resize_handler(entries) {
entries.forEach(function (e) {
var evt = [EVENT_TAG.CANVAS_RESIZED,
[0, e.target.canvas,
caml_int64_of_float(e.timeStamp * 1000.0),
[0, e.target.clientWidth, e.target.clientHeight]]];
_ml_canvas_process_event(evt);
});
return false;
}

//Provides: _frame_handler
//Requires: _ml_canvas_process_event, EVENT_TAG
//Requires: caml_int64_of_float
Expand Down Expand Up @@ -588,7 +616,7 @@ var _next_id = 0;

//Provides: _ml_canvas_decorate
//Requires: caml_jsstring_of_string
function _ml_canvas_decorate(header, resizeable, minimize,
function _ml_canvas_decorate(header, minimize,
maximize, close, title) {
var width = header.width;
var ctxt = header.getContext("2d");
Expand All @@ -613,10 +641,11 @@ function _ml_canvas_decorate(header, resizeable, minimize,
}

//Provides: ml_canvas_create_onscreen
//Requires: _ml_canvas_ensure_initialized, _ml_canvas_valid_canvas_size, _next_id, _header_down_handler, _surface_down_handler, _up_handler, _move_handler, _ml_canvas_decorate, Optional_bool_val, Optional_val
//Requires: _ml_canvas_ensure_initialized, _ml_canvas_valid_canvas_size, _resize, _next_id, _header_down_handler
//Requires: _surface_down_handler, _up_handler, _move_handler, _ml_canvas_decorate, Optional_bool_val, Optional_val
//Requires: caml_invalid_argument
function ml_canvas_create_onscreen(autocmmit, decorated, resizeable, minimize,
maximize, close, title, pos, size) {
function ml_canvas_create_onscreen(autocommit, decorated, resizeable, minimize,
maximize, close, title, target, pos, size) {

_ml_canvas_ensure_initialized();

Expand All @@ -631,17 +660,23 @@ function ml_canvas_create_onscreen(autocmmit, decorated, resizeable, minimize,
var y = pos[2];

var autocommit = Optional_bool_val(autocommit, true);
var decorated = Optional_bool_val(decorated, true);
var decorated = false; // Optional_bool_val(decorated, true);
var resizeable = Optional_bool_val(resizeable, true);
var minimize = Optional_bool_val(minimize, true);
var maximize = Optional_bool_val(maximize, true);
var close = Optional_bool_val(close, true);
var title = Optional_val(title, null);
var target = Optional_val(target, null);
target = document.getElementById(target);
if(target == null) {
target = document.body;
}

var id = ++_next_id;

var canvas = {
name: title,
target: target,
frame: null,
header: null,
surface: null,
Expand All @@ -661,16 +696,18 @@ function ml_canvas_create_onscreen(autocmmit, decorated, resizeable, minimize,

var frame = document.createElement("div");
frame.id = "f" + id;
frame.style.width = width + "px";
frame.style.height = height + header_height + "px";
if (resizeable == true) {
frame.style.width = "100%";
frame.style.height = "100%";
} else {
frame.style.width = width + "px";
frame.style.height = height + header_height + "px";
}
frame.style.visibility = "hidden";
frame.style.position = "absolute";
frame.style.left = x + "px";
frame.style.top = y + "px";
frame.oncontextmenu = function() { return false; }
frame.canvas = canvas;
canvas.frame = frame;
document.body.appendChild(frame);
target.appendChild(frame);

var header = null;
if (decorated === true) {
Expand All @@ -679,8 +716,7 @@ function ml_canvas_create_onscreen(autocmmit, decorated, resizeable, minimize,
header.id = "h" + id;
header.width = width;
header.height = 30;
header.style.position = "absolute";
_ml_canvas_decorate(header, resizeable, minimize, maximize, close, title);
_ml_canvas_decorate(header, minimize, maximize, close, title);
header.onmousedown = _header_down_handler;
header.canvas = canvas;
canvas.header = header;
Expand All @@ -691,13 +727,17 @@ function ml_canvas_create_onscreen(autocmmit, decorated, resizeable, minimize,
surface.id = "s" + id;
surface.width = width;
surface.height = height;
surface.style.position = "absolute"
surface.style.top = header_height + "px";
surface.onmousedown = _surface_down_handler;
surface.canvas = canvas;
canvas.surface = surface;
frame.appendChild(surface);

if (resizeable === true) {
surface.style.width = "100%";
surface.style.height = "100%";
_resize.observe(surface);
}

var ctxt = surface.getContext("2d");
ctxt.globalAlpha = 1.0;
ctxt.lineWidth = 1.0;
Expand Down Expand Up @@ -907,7 +947,7 @@ function ml_canvas_set_size(canvas, size) {
var img = canvas.ctxt.getImageData(0, 0, canvas.width, canvas.height);
if (canvas.header !== null) {
canvas.header.width = width;
_ml_canvas_decorate(canvas.header, canvas.resizeable, canvas.minimize,
_ml_canvas_decorate(canvas.header, canvas.minimize,
canvas.maximize, canvas.close, canvas.name);
}
canvas.surface.width = canvas.width = width;
Expand Down Expand Up @@ -1551,16 +1591,16 @@ function ml_canvas_key_of_int(keycode) {
/* Backend */

//Provides: ml_canvas_init
//Requires: _key_down_handler, _key_up_handler, _up_handler, _move_handler, _frame_handler, _ml_canvas_initialized
//Requires: caml_list_to_js_array
//Requires: _key_down_handler, _key_up_handler, _up_handler, _move_handler, _resize_handler, _frame_handler
//Requires: _ml_canvas_initialized, caml_list_to_js_array
function ml_canvas_init() {
if (_ml_canvas_initialized === true) {
return 0;
}
document.onkeydown = _key_down_handler;
document.onkeyup = _key_up_handler;
document.onmouseup = _up_handler;
document.onmousemove = _move_handler;
document.addEventListener("keydown", _key_down_handler, {passive: true});
document.addEventListener("keyup", _key_up_handler, {passive: true});
document.addEventListener("mouseup", _up_handler, {passive: true});
document.addEventListener("mousemove", _move_handler, {passive: true});
window.requestAnimationFrame(_frame_handler);
_ml_canvas_initialized = true;
return 0;
Expand Down
Loading