PointerEvents: from mouse events to pointer events v1

added LiteGraph.pointerevents_method with default "pointer"
replaced EventListeners with pointerevents_method+"down", "up", etc..
replaced e.localX (and Y) for e.clientX (Y)
fixed e.clientX is not writable

TODO: finish checks and clean
version with console.log("pointerevents..) enabled
alpha working for mobile, touch enabled
This commit is contained in:
atlasan
2021-10-02 14:26:15 +02:00
parent d3d2586039
commit a66d822e2a

View File

@@ -98,7 +98,10 @@
searchbox_extras: {}, //used to add extra features to the search box
auto_sort_node_types: false, // If set to true, will automatically sort node types / categories in the context menus
pointerevents_method: "pointer", // "mouse"|"pointer" use mouse for retrocompatibility issues
// TODO implement pointercancel, gotpointercapture, lostpointercapture, (pointerover, pointerout if necessary)
/**
* Register a node class so it can be listed when the user wants to create a new one
* @method registerNodeType
@@ -4441,8 +4444,9 @@ LGraphNode.prototype.executeAction = function(action)
this._binded_mouse_callback = this.onMouse.bind(this);
element.addEventListener("mousedown", this._binded_mouse_callback);
element.addEventListener("mousemove", this._binded_mouse_callback);
element.addEventListener(LiteGraph.pointerevents_method+"down", this._binded_mouse_callback);
element.addEventListener(LiteGraph.pointerevents_method+"move", this._binded_mouse_callback);
element.addEventListener(LiteGraph.pointerevents_method+"up", this._binded_mouse_callback);
element.addEventListener(
"mousewheel",
@@ -4488,20 +4492,22 @@ LGraphNode.prototype.executeAction = function(action)
e.canvasx = x;
e.canvasy = y;
e.dragging = this.dragging;
var is_inside = !this.viewport || ( this.viewport && x >= this.viewport[0] && x < (this.viewport[0] + this.viewport[2]) && y >= this.viewport[1] && y < (this.viewport[1] + this.viewport[3]) );
console.log("pointerevents:: DragAndScale onMouse "+e.type+" "+is_inside);
var ignore = false;
if (this.onmouse) {
ignore = this.onmouse(e);
}
if (e.type == "mousedown" && is_inside) {
if (e.type == LiteGraph.pointerevents_method+"down" && is_inside) {
this.dragging = true;
canvas.removeEventListener( "mousemove", this._binded_mouse_callback );
document.body.addEventListener( "mousemove", this._binded_mouse_callback );
document.body.addEventListener( "mouseup", this._binded_mouse_callback );
} else if (e.type == "mousemove") {
canvas.removeEventListener( LiteGraph.pointerevents_method+"move", this._binded_mouse_callback );
document.body.addEventListener( LiteGraph.pointerevents_method+"move", this._binded_mouse_callback );
document.body.addEventListener( LiteGraph.pointerevents_method+"up", this._binded_mouse_callback );
} else if (e.type == LiteGraph.pointerevents_method+"move") {
if (!ignore) {
var deltax = x - this.last_mouse[0];
var deltay = y - this.last_mouse[1];
@@ -4509,11 +4515,11 @@ LGraphNode.prototype.executeAction = function(action)
this.mouseDrag(deltax, deltay);
}
}
} else if (e.type == "mouseup") {
} else if (e.type == LiteGraph.pointerevents_method+"up") {
this.dragging = false;
document.body.removeEventListener( "mousemove", this._binded_mouse_callback );
document.body.removeEventListener( "mouseup", this._binded_mouse_callback );
canvas.addEventListener("mousemove", this._binded_mouse_callback );
document.body.removeEventListener( LiteGraph.pointerevents_method+"move", this._binded_mouse_callback );
document.body.removeEventListener( LiteGraph.pointerevents_method+"up", this._binded_mouse_callback );
canvas.addEventListener(LiteGraph.pointerevents_method+"move", this._binded_mouse_callback );
} else if ( is_inside &&
(e.type == "mousewheel" ||
e.type == "wheel" ||
@@ -4982,8 +4988,8 @@ LGraphNode.prototype.executeAction = function(action)
}
//input: (move and up could be unbinded)
this._mousemove_callback = this.processMouseMove.bind(this);
this._mouseup_callback = this.processMouseUp.bind(this);
// why here? this._mousemove_callback = this.processMouseMove.bind(this);
// why here? this._mouseup_callback = this.processMouseUp.bind(this);
if (!skip_events) {
this.bindEvents();
@@ -4992,6 +4998,7 @@ LGraphNode.prototype.executeAction = function(action)
//used in some events to capture them
LGraphCanvas.prototype._doNothing = function doNothing(e) {
console.log("pointerevents:: _doNothing "+e.type);
e.preventDefault();
return false;
};
@@ -5010,6 +5017,8 @@ LGraphNode.prototype.executeAction = function(action)
return;
}
console.log("pointerevents:: binEvents");
var canvas = this.canvas;
var ref_window = this.getCanvasWindow();
@@ -5017,12 +5026,19 @@ LGraphNode.prototype.executeAction = function(action)
this._mousedown_callback = this.processMouseDown.bind(this);
this._mousewheel_callback = this.processMouseWheel.bind(this);
this._touch_callback = this.touchHandler.bind(this);
// why not binded here? this._mousemove_callback = this.processMouseMove.bind(this);
this._mousemove_callback = this.processMouseMove.bind(this);
this._mouseup_callback = this.processMouseUp.bind(this);
//touch events -- THIS WAY DOES NOT WORK, finish implementing pointerevents, than clean the touchevents
//this._touch_callback = this.touchHandler.bind(this);
canvas.addEventListener("pointerdown", this._mousedown_callback, true); //down do not need to store the binded
canvas.addEventListener("mousemove", this._mousemove_callback);
canvas.addEventListener(LiteGraph.pointerevents_method+"down", this._mousedown_callback, true); //down do not need to store the binded
canvas.addEventListener("mousewheel", this._mousewheel_callback, false);
canvas.addEventListener(LiteGraph.pointerevents_method+"up", this._mouseup_callback, true);
canvas.addEventListener(LiteGraph.pointerevents_method+"move", this._mousemove_callback);
canvas.addEventListener("contextmenu", this._doNothing);
canvas.addEventListener(
"DOMMouseScroll",
@@ -5030,14 +5046,14 @@ LGraphNode.prototype.executeAction = function(action)
false
);
//touch events
//if( 'touchstart' in document.documentElement )
//touch events -- THIS WAY DOES NOT WORK, finish implementing pointerevents, than clean the touchevents
/*if( 'touchstart' in document.documentElement )
{
canvas.addEventListener("touchstart", this._touch_callback, true);
canvas.addEventListener("touchmove", this._touch_callback, true);
canvas.addEventListener("touchend", this._touch_callback, true);
canvas.addEventListener("touchcancel", this._touch_callback, true);
}
}*/
//Keyboard ******************
this._key_callback = this.processKey.bind(this);
@@ -5066,10 +5082,14 @@ LGraphNode.prototype.executeAction = function(action)
return;
}
console.log("pointerevents:: unbindEvents");
var ref_window = this.getCanvasWindow();
var document = ref_window.document;
this.canvas.removeEventListener("mousedown", this._mousedown_callback);
this.canvas.removeEventListener(LiteGraph.pointerevents_method+"move", this._mousedown_callback);
this.canvas.removeEventListener(LiteGraph.pointerevents_method+"up", this._mousedown_callback);
this.canvas.removeEventListener(LiteGraph.pointerevents_method+"down", this._mousedown_callback);
this.canvas.removeEventListener(
"mousewheel",
this._mousewheel_callback
@@ -5084,10 +5104,11 @@ LGraphNode.prototype.executeAction = function(action)
this.canvas.removeEventListener("drop", this._ondrop_callback);
this.canvas.removeEventListener("dragenter", this._doReturnTrue);
this.canvas.removeEventListener("touchstart", this._touch_callback );
//touch events -- THIS WAY DOES NOT WORK, finish implementing pointerevents, than clean the touchevents
/*this.canvas.removeEventListener("touchstart", this._touch_callback );
this.canvas.removeEventListener("touchmove", this._touch_callback );
this.canvas.removeEventListener("touchend", this._touch_callback );
this.canvas.removeEventListener("touchcancel", this._touch_callback );
this.canvas.removeEventListener("touchcancel", this._touch_callback );*/
this._mousedown_callback = null;
this._mousewheel_callback = null;
@@ -5217,7 +5238,7 @@ LGraphNode.prototype.executeAction = function(action)
}
LGraphCanvas.prototype.processMouseDown = function(e) {
if( this.set_canvas_dirty_on_mouse_event )
this.dirty_canvas = true;
@@ -5232,9 +5253,10 @@ LGraphNode.prototype.executeAction = function(action)
LGraphCanvas.active_canvas = this;
var that = this;
var x = e.localX;
var y = e.localY;
var x = e.clientX;
var y = e.clientY;
//console.log(y,this.viewport);
console.log("pointerevents:: processMouseDown "+e.pointerId+" "+e.isPrimary+" :: "+x+" "+y);
this.ds.viewport = this.viewport;
var is_inside = !this.viewport || ( this.viewport && x >= this.viewport[0] && x < (this.viewport[0] + this.viewport[2]) && y >= this.viewport[1] && y < (this.viewport[1] + this.viewport[3]) );
@@ -5242,9 +5264,9 @@ LGraphNode.prototype.executeAction = function(action)
//move mouse move event to the window in case it drags outside of the canvas
if(!this.options.skip_events)
{
this.canvas.removeEventListener("mousemove", this._mousemove_callback);
ref_window.document.addEventListener( "mousemove", this._mousemove_callback, true ); //catch for the entire window
ref_window.document.addEventListener( "mouseup", this._mouseup_callback, true );
this.canvas.removeEventListener(LiteGraph.pointerevents_method+"move", this._mousemove_callback);
ref_window.document.addEventListener( LiteGraph.pointerevents_method+"move", this._mousemove_callback, true ); //catch for the entire window
ref_window.document.addEventListener( LiteGraph.pointerevents_method+"up", this._mouseup_callback, true );
}
if(!is_inside)
@@ -5254,9 +5276,9 @@ LGraphNode.prototype.executeAction = function(action)
var skip_dragging = false;
var skip_action = false;
var now = LiteGraph.getTime();
var is_double_click = (now - this.last_mouseclick < 300) && (e.isPrimary);
this.mouse[0] = e.localX;
this.mouse[1] = e.localY;
var is_double_click = (now - this.last_mouseclick < 300) && (e.isPrimary!==undefined && e.isPrimary);
this.mouse[0] = e.clientX;
this.mouse[1] = e.clientY;
this.graph_mouse[0] = e.canvasX;
this.graph_mouse[1] = e.canvasY;
this.last_click_position = [this.mouse[0],this.mouse[1]];
@@ -5508,8 +5530,10 @@ LGraphNode.prototype.executeAction = function(action)
}
if (!skip_action && clicking_canvas_bg && this.allow_dragcanvas) {
this.dragging_canvas = true;
console.log("pointerevents:: dragging_canvas start");
this.dragging_canvas = true;
}
} else if (e.which == 2) {
//middle button
} else if (e.which == 3) {
@@ -5522,8 +5546,8 @@ LGraphNode.prototype.executeAction = function(action)
//if(this.node_selected != prev_selected)
// this.onNodeSelectionChange(this.node_selected);
this.last_mouse[0] = e.localX;
this.last_mouse[1] = e.localY;
this.last_mouse[0] = e.clientX;
this.last_mouse[1] = e.clientY;
this.last_mouseclick = LiteGraph.getTime();
this.last_mouse_dragging = true;
@@ -5571,7 +5595,7 @@ LGraphNode.prototype.executeAction = function(action)
LGraphCanvas.active_canvas = this;
this.adjustMouseEvent(e);
var mouse = [e.localX, e.localY];
var mouse = [e.clientX, e.clientY];
this.mouse[0] = mouse[0];
this.mouse[1] = mouse[1];
var delta = [
@@ -5582,8 +5606,15 @@ LGraphNode.prototype.executeAction = function(action)
this.graph_mouse[0] = e.canvasX;
this.graph_mouse[1] = e.canvasY;
console.log("pointerevents:: processMouseMove "+e.pointerId+" "+e.isPrimary);
//convertEventToCanvasOffset
console.log(mouse);
console.log(this.graph_mouse);
//console.log(delta);
if(this.block_click)
{
console.log("pointerevents:: processMouseMove block_click");
e.preventDefault();
return false;
}
@@ -5624,6 +5655,7 @@ LGraphNode.prototype.executeAction = function(action)
}
this.dirty_bgcanvas = true;
} else if (this.dragging_canvas) {
//console.log("pointerevents:: processMouseMove is dragging_canvas");
this.ds.offset[0] += delta[0] / this.ds.scale;
this.ds.offset[1] += delta[1] / this.ds.scale;
this.dirty_canvas = true;
@@ -5784,6 +5816,16 @@ LGraphNode.prototype.executeAction = function(action)
**/
LGraphCanvas.prototype.processMouseUp = function(e) {
//early exit for extra pointer
if(e.isPrimary!==undefined && !e.isPrimary){
/*e.stopPropagation();
e.preventDefault();*/
console.log("pointerevents:: processMouseUp pointerN_stop "+e.pointerId+" "+e.isPrimary);
return false;
}
console.log("pointerevents:: processMouseUp "+e.pointerId+" "+e.isPrimary+" :: "+e.clientX+" "+e.clientY);
if( this.set_canvas_dirty_on_mouse_event )
this.dirty_canvas = true;
@@ -5797,9 +5839,11 @@ LGraphNode.prototype.executeAction = function(action)
//restore the mousemove event back to the canvas
if(!this.options.skip_events)
{
document.removeEventListener("mousemove",this._mousemove_callback,true);
this.canvas.addEventListener("mousemove",this._mousemove_callback,true);
document.removeEventListener("mouseup", this._mouseup_callback, true);
console.log("pointerevents:: processMouseUp removeEventListener");
// why move listener from document to canvas?
document.removeEventListener(LiteGraph.pointerevents_method+"move",this._mousemove_callback,true);
this.canvas.addEventListener(LiteGraph.pointerevents_method+"move",this._mousemove_callback,true);
document.removeEventListener(LiteGraph.pointerevents_method+"up", this._mouseup_callback, true);
}
this.adjustMouseEvent(e);
@@ -5810,10 +5854,12 @@ LGraphNode.prototype.executeAction = function(action)
if(this.block_click)
{
console.log("foo");
console.log("pointerevents:: processMouseUp block_clicks");
this.block_click = false; //used to avoid sending twice a click in a immediate button
}
console.log("pointerevents:: processMouseUp which: "+e.which);
if (e.which == 1) {
if( this.node_widget )
@@ -6030,6 +6076,7 @@ LGraphNode.prototype.executeAction = function(action)
this.graph.change();
console.log("pointerevents:: processMouseUp stopPropagation");
e.stopPropagation();
e.preventDefault();
return false;
@@ -6048,8 +6095,8 @@ LGraphNode.prototype.executeAction = function(action)
this.adjustMouseEvent(e);
var x = e.localX;
var y = e.localY;
var x = e.clientX;
var y = e.clientY;
var is_inside = !this.viewport || ( this.viewport && x >= this.viewport[0] && x < (this.viewport[0] + this.viewport[2]) && y >= this.viewport[1] && y < (this.viewport[1] + this.viewport[3]) );
if(!is_inside)
return;
@@ -6062,8 +6109,8 @@ LGraphNode.prototype.executeAction = function(action)
scale *= 1 / 1.1;
}
//this.setZoom( scale, [ e.localX, e.localY ] );
this.ds.changeScale(scale, [e.localX, e.localY]);
//this.setZoom( scale, [ e.clientX, e.clientY ] );
this.ds.changeScale(scale, [e.clientX, e.clientY]);
this.graph.change();
@@ -6326,8 +6373,8 @@ LGraphNode.prototype.executeAction = function(action)
LGraphCanvas.prototype.processDrop = function(e) {
e.preventDefault();
this.adjustMouseEvent(e);
var x = e.localX;
var y = e.localY;
var x = e.clientX;
var y = e.clientY;
var is_inside = !this.viewport || ( this.viewport && x >= this.viewport[0] && x < (this.viewport[0] + this.viewport[2]) && y >= this.viewport[1] && y < (this.viewport[1] + this.viewport[3]) );
if(!is_inside)
return;
@@ -6622,23 +6669,26 @@ LGraphNode.prototype.executeAction = function(action)
* @method adjustMouseEvent
**/
LGraphCanvas.prototype.adjustMouseEvent = function(e) {
if (this.canvas) {
if (this.canvas) {
var b = this.canvas.getBoundingClientRect();
e.localX = e.clientX - b.left;
e.localY = e.clientY - b.top;
clientX_rel = e.clientX - b.left;
clientY_rel = e.clientY - b.top;
} else {
e.localX = e.clientX;
e.localY = e.clientY;
clientX_rel = e.clientX;
clientY_rel = e.clientY;
}
e.deltaX = clientX_rel - this.last_mouse_position[0];
e.deltaY = clientY_rel- this.last_mouse_position[1];
e.deltaX = e.localX - this.last_mouse_position[0];
e.deltaY = e.localY - this.last_mouse_position[1];
this.last_mouse_position[0] = clientX_rel;
this.last_mouse_position[1] = clientY_rel;
this.last_mouse_position[0] = e.localX;
this.last_mouse_position[1] = e.localY;
e.canvasX = e.localX / this.ds.scale - this.ds.offset[0];
e.canvasY = e.localY / this.ds.scale - this.ds.offset[1];
e.canvasX = clientX_rel / this.ds.scale - this.ds.offset[0];
e.canvasY = clientY_rel / this.ds.scale - this.ds.offset[1];
console.log("pointerevents:: adjustMouseEvent "+e.clientX+":"+e.clientY+" "+clientX_rel+":"+clientY_rel+" "+e.canvasX+":"+e.canvasY);
};
/**
@@ -8951,7 +9001,7 @@ LGraphNode.prototype.executeAction = function(action)
//inside widget
switch (w.type) {
case "button":
if (event.type === "mousedown") {
if (event.type === LiteGraph.pointerevents_method+"down") {
if (w.callback) {
setTimeout(function() {
w.callback(w, that, node, pos, event);
@@ -8975,7 +9025,7 @@ LGraphNode.prototype.executeAction = function(action)
case "number":
case "combo":
var old_value = w.value;
if (event.type == "mousemove" && w.type == "number") {
if (event.type == LiteGraph.pointerevents_method+"move" && w.type == "number") {
w.value += event.deltaX * 0.1 * (w.options.step || 1);
if ( w.options.min != null && w.value < w.options.min ) {
w.value = w.options.min;
@@ -8983,7 +9033,7 @@ LGraphNode.prototype.executeAction = function(action)
if ( w.options.max != null && w.value > w.options.max ) {
w.value = w.options.max;
}
} else if (event.type == "mousedown") {
} else if (event.type == LiteGraph.pointerevents_method+"down") {
var values = w.options.values;
if (values && values.constructor === Function) {
values = w.options.values(w, node);
@@ -9038,7 +9088,7 @@ LGraphNode.prototype.executeAction = function(action)
}
}
} //end mousedown
else if(event.type == "mouseup" && w.type == "number")
else if(event.type == LiteGraph.pointerevents_method+"up" && w.type == "number")
{
var delta = x < 40 ? -1 : x > widget_width - 40 ? 1 : 0;
if (event.click_time < 200 && delta == 0) {
@@ -9060,7 +9110,7 @@ LGraphNode.prototype.executeAction = function(action)
this.dirty_canvas = true;
break;
case "toggle":
if (event.type == "mousedown") {
if (event.type == LiteGraph.pointerevents_method+"down") {
w.value = !w.value;
setTimeout(function() {
inner_value_change(w, w.value);
@@ -9069,7 +9119,7 @@ LGraphNode.prototype.executeAction = function(action)
break;
case "string":
case "text":
if (event.type == "mousedown") {
if (event.type == LiteGraph.pointerevents_method+"down") {
this.prompt("Value",w.value,function(v) {
this.value = v;
inner_value_change(this, v);
@@ -9228,7 +9278,11 @@ LGraphNode.prototype.executeAction = function(action)
return; //disabled
};
LGraphCanvas.prototype.touchHandler = function(event) {
/* this is an implementation for touch not in production and not ready
* the idea is maybe good: simulate a similar event
* so let's try with pointerevents (working with both mouse and touch), and simulate the old mouseevents IF NECESSARY for retrocompatibility: existing old good nodes
*/
/*LGraphCanvas.prototype.touchHandler = function(event) {
//alert("foo");
var touches = event.changedTouches,
first = touches[0],
@@ -9270,12 +9324,12 @@ LGraphNode.prototype.executeAction = function(action)
false,
false,
false,
0 /*left*/,
0, //left
null
);
first.target.dispatchEvent(simulatedEvent);
event.preventDefault();
};
};*/
/* CONTEXT MENU ********************/
@@ -9771,7 +9825,7 @@ LGraphNode.prototype.executeAction = function(action)
dialog.style.transform = "scale(" + this.ds.scale + ")";
}
dialog.addEventListener("mouseleave", function(e) {
dialog.addEventListener(LiteGraph.pointerevents_method+"leave", function(e) {
if (!modified) {
dialog.close();
}
@@ -9876,14 +9930,14 @@ LGraphNode.prototype.executeAction = function(action)
dialog.style.transform = "scale(" + this.ds.scale + ")";
}
dialog.addEventListener("mouseenter", function(e) {
dialog.addEventListener(LiteGraph.pointerevents_method+"enter", function(e) {
if (timeout_close) {
clearTimeout(timeout_close);
timeout_close = null;
}
});
dialog.addEventListener("mouseleave", function(e) {
dialog.addEventListener(LiteGraph.pointerevents_method+"leave", function(e) {
//dialog.close();
timeout_close = setTimeout(function() {
dialog.close();
@@ -11499,7 +11553,7 @@ LGraphNode.prototype.executeAction = function(action)
//this prevents the default context browser menu to open in case this menu was created when pressing right button
root.addEventListener(
"mouseup",
LiteGraph.pointerevents_method+"up",
function(e) {
e.preventDefault();
return true;
@@ -11520,7 +11574,7 @@ LGraphNode.prototype.executeAction = function(action)
);
root.addEventListener(
"mousedown",
LiteGraph.pointerevents_method+"down",
function(e) {
if (e.button == 2) {
that.close();
@@ -11569,7 +11623,7 @@ LGraphNode.prototype.executeAction = function(action)
}
//close on leave
root.addEventListener("mouseleave", function(e) {
root.addEventListener(LiteGraph.pointerevents_method+"leave", function(e) {
if (that.lock) {
return;
}
@@ -11580,7 +11634,7 @@ LGraphNode.prototype.executeAction = function(action)
//that.close(e);
});
root.addEventListener("mouseenter", function(e) {
root.addEventListener(LiteGraph.pointerevents_method+"enter", function(e) {
if (root.closing_timer) {
clearTimeout(root.closing_timer);
}
@@ -11681,7 +11735,7 @@ LGraphNode.prototype.executeAction = function(action)
element.addEventListener("click", inner_onclick);
}
if (options.autoopen) {
element.addEventListener("mouseenter", inner_over);
element.addEventListener(LiteGraph.pointerevents_method+"enter", inner_over);
}
function inner_over(e) {
@@ -11776,7 +11830,7 @@ LGraphNode.prototype.executeAction = function(action)
e &&
!ContextMenu.isCursorOverElement(e, this.parentMenu.root)
) {
ContextMenu.trigger(this.parentMenu.root, "mouseleave", e);
ContextMenu.trigger(this.parentMenu.root, LiteGraph.pointerevents_method+"leave", e);
}
}
if (this.current_submenu) {